Elasticsearch的基本使用
1.必要的配置
@Configuration
@EnableConfigurationProperties(EsProperties.class)
public class EsConfiguration {
@Bean
public ElasticsearchClient esClient(EsProperties esProperties) {
// Create the low-level client
RestClient restClient = RestClient.builder(
new HttpHost(esProperties.getHost(), esProperties.getPort())).build();
// 创建 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 添加 JavaTimeModule 以支持 LocalDateTime 类型
objectMapper.registerModule(new JavaTimeModule());
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper(objectMapper));
// And create the API client
ElasticsearchClient esClient = new ElasticsearchClient(transport);
return esClient;
}
public class EsProperties {
/**
* es host
/
private String host;
/*
* es 端口
*/
private Integer port;
host与post可以通过@ConfigurationProperties从配置中获取
1.range查询
public void testRangeQuery() throws IOException {
SearchResponse
s.index("items")
.query(q->q.range(r->r.field("price").gte(JsonData.of(100000)).lte(JsonData.of(200000))))
, ItemDoc.class);
extracted(response);
}
private static void extracted(SearchResponse<ItemDoc> response) {
log.info("总共{}条数据", response.hits().total().value());
List<Hit<ItemDoc>> hits = response.hits().hits();
hits.forEach(hit->{
System.out.println(hit.source());
});
}
2.match查询
public void testMatchQuery() throws IOException {
SearchResponse
s.index("items")
.query(q->q.match(m->m.field("name").query("健康早餐奶")))
, ItemDoc.class);
extracted(response);
}
3.bool查询
public void testBoolQuery() throws IOException {
SearchResponse
s.index("items")
.query(q->q.bool(b->b
.must(m->m.match(match->match.field("name").query("手机")))
.mustNot(m->m.range(t->t.field("price").gte(JsonData.of(25000))))
.should(m->m.term(t->t.field("brand").value("小米")))
.should(m->m.term(t->t.field("brand").value("vivo")))
))
, ItemDoc.class);
extracted(response);
}
数据处理extracted:
private static void extracted(SearchResponse
log.info("总共{}条数据", response.hits().total().value());
List<Hit
hits.forEach(hit->{
System.out.println(hit.source());
});
}
multi_match查询
public void testMultiMatchQuery() throws IOException {
SearchResponse
s.index("items")
.query(q->q.multiMatch(m->m.fields("name","category").query("德国进口牛奶")))
.sort(s1->s1.field(f->f.field("price").order(SortOrder.Desc)))
.sort(s2->s2.field(f->f.field("stock").order(SortOrder.Asc)))
.from(0)
.size(20)
, ItemDoc.class);
extracted(response);
}
term查询
SearchResponse
s.index("items")
.query(q->q.term(t->t.field("category").value("拉杆箱")))
, ItemDoc.class);
extracted(response);
}
高亮显示
public void testHightLight() throws IOException {
SearchResponse
s.index("items")
.query(q->q.match(m->m.field("brand").query("小米")))
.highlight(h->h.fields("name",f->f.preTags(" ").postTags("").requireFieldMatch(false)))
, ItemDoc.class);
long total = response.hits().total().value();
log.info("总共{}条数据", total);
List<Hit
for (Hit
ItemDoc itemDoc = hit.source();
Map<String, List
if (highlightFields != null && highlightFields.containsKey("name")) {
List
if(name != null&& name.size() > 0){
itemDoc.setName(name.get(0));
System.out.println(itemDoc);
}
}
}
}
通过Bool为核心的电商平台查询核心功能(加上名字的高亮显示):
public PageDTO
log.info("查询条件为{}",query);
// 分页查询
SearchResponse
s.index("items")
.query(q -> q.bool(b -> {
// 检查 key 是否为空
if (StrUtil.isNotBlank(query.getKey())) {
b.must(m -> m.match(match -> match.field("name").query(query.getKey())));
}
// 检查 minPrice 是否有效
if (query.getMinPrice() != null) {
b.must(m -> m.range(t -> t.field("price").gte(JsonData.of(query.getMinPrice()))));
}
// 检查 maxPrice 是否有效
if (query.getMaxPrice() != null) {
b.must(m -> m.range(t -> t.field("price").lte(JsonData.of(query.getMaxPrice()))));
}
// 检查 brand 是否为空
if (StrUtil.isNotBlank(query.getBrand())) {
b.should(m -> m.term(t -> t.field("brand").value(query.getBrand())));
}
// 检查 category 是否为空
if (StrUtil.isNotBlank(query.getCategory())) {
b.should(m -> m.term(t -> t.field("category").value(query.getCategory())));
}
return b;
})).from(0).size(1000).highlight(h -> h.fields("name", f -> f.preTags(" ").postTags("").requireFieldMatch(false)))
, ItemDoc.class);
// 封装并返回
List<Hit<ItemDoc>> hits = response.hits().hits();
for (Hit<ItemDoc> hit : hits) {
ItemDoc itemDoc = hit.source();
Map<String, List<String>> highlightFields = hit.highlight();
if (highlightFields != null && highlightFields.containsKey("name")) {
List<String> name = highlightFields.get("name");
if (name != null && name.size() > 0) {
itemDoc.setName(name.get(0));
}
}
}
List<ItemDoc> list = new ArrayList<>();
if (CollUtils.isNotEmpty(hits)) {
list = hits.stream().map(Hit::source).collect(Collectors.toList());
}
//List<ItemDTO> result = BeanUtil.copyToList(list, ItemDTO.class);
Page<ItemDoc> pageResult = new Page<>(query.getPageNo(), query.getPageSize());
System.out.println(response.hits().total().value());
pageResult.setTotal(response.hits().total().value());
pageResult.setRecords(list);
return PageDTO.of(pageResult, ItemDoc.class);
}