一、ElasticsearchRestTemplate
ElasticsearchRestTemplate是Spring封装ES客户端的一些原生api模板,方便实现一些查询,和ElasticsearchTemplate一样,但是目前spring推荐使用前者,是一种更高级的REST风格api。
二、NativeSearchQuery
这是一个原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询。
三、QueryBuilders
QueryBuilders是ES中的查询条件构造器
3.1 精准查询(查询关键字(或者关键字分词后),必须与目标分词结果完全匹配)
//1.指定字符串作为关键词查询,关键词支持分词
//查询name字段中包含 “酸菜鱼”、“酸菜”、“鱼”这几个字段的document;相当于先将酸菜鱼先分词再查询;
QueryBuilders.queryStringQuery("酸菜鱼").defaultField("description");
//不指定Field,查询所有的Fidld
QueryBuilders.queryStringQuery("酸菜鱼");
//指定多个Feild
QueryBuilders.queryStringQuery("酸菜鱼").field("name").field("description");
//2.以关键字“酸菜鱼”,关键字不支持分词
QueryBuilders.termQuery("name","酸菜鱼");
QueryBuilders.termsQuery("name","酸菜鱼","鱼");
//3.以关键字“酸菜鱼”,关键字支持分词
QueryBuilders.matchQuery("name","酸菜鱼");
QueryBuilders.multiMatchQuery("name","酸菜鱼","鱼");
3.2 模糊查询(查询关键字与目标关键字可以模糊匹配)
//1.左右模糊查询,其中fuzziness的参数作用是在查询时,es动态的将查询关键词前后增加或者删除一个词,然后进行匹配
QueryBuilders.fuzzyQuery("name","酸菜鱼").fuzziness(Fuzziness.ONE);
//2.前缀查询,查询name中以“酸菜鱼”为前缀的document;
QueryBuilders.wildcardQuery("name","酸菜鱼");
//3.通配符查询,支持*和?,?表示单个字符;注意不建议将通配符作为前缀,否则导致查询很慢
QueryBuilders.wildcardQuery("name","酸*菜鱼");
QueryBuilders.wildcardQuery("name","酸?菜鱼");
3.3 范围查询 rangeQuery()
//1.闭区间查询
QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2");
//2.开区间查询,默认是true,也就是包含
QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2").includeUpper(false).includeLower(false);
//大于
QueryBuilders.rangeQuery("fieldName").gt("fieldValue");
//大于等于
QueryBuilders.rangeQuery("fieldName").gte("fieldValue");
//小于
QueryBuilders.rangeQuery("fieldName").lt("fieldValue");
//小于等于
QueryBuilders.rangeQuery("fieldName").lte("fieldValue");
3.4 多个关键字查询 boolQuery()
//多个关键字组合查询
//文档必须完全匹配条件,相当于and
QueryBuilders.boolQuery().must();
//文档必须不匹配条件,相当于not
QueryBuilders.boolQuery().mustNot();
//至少满足一个条件,这个文档就符合should,相当于or
QueryBuilders.boolQuery().should();
//使用示例如下
NativeSearchQueryBuilder nativeSearchQueryBuilder=new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.boolQuery()
.should(QueryBuilders.termQuery("name","酸菜鱼"))
.should(QueryBuilders.termQuery("name","鱼肉"))
.mustNot(QueryBuilders.termQuery("name","鸡肉")));
3.5 条件查询+分页+排序+字段高亮
public Page<DishDtoEs> pageES(int page, int pageSize, String name) {
Page pageInfo = new Page<>();
PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//给name字段设置高亮显示
if (StringUtils.isNotEmpty(name)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("name", name));
queryBuilder.withHighlightFields(new HighlightBuilder.Field("name"))
.withHighlightBuilder(new HighlightBuilder().preTags("<font style='color: red;'>").postTags("</font>"));
}
//查询条件
queryBuilder.withQuery(boolQueryBuilder);
//排序
queryBuilder.withSort(SortBuilders.fieldSort("updateTime").order(SortOrder.DESC));
//设置分页
queryBuilder.withPageable(pageRequest);
SearchHits<DishDtoEs> search = elasticsearchRestTemplate.search(queryBuilder.build(), DishDtoEs.class);
List<SearchHit<DishDtoEs>> searchHits = search.getSearchHits();
List<DishDtoEs> result=new ArrayList<>(searchHits.size());
//替换高亮内容
for (SearchHit<DishDtoEs> searchHit:searchHits){
//高亮的内容
Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
//将高亮的内容填充到content中
searchHit.getContent().setName(highlightFields.get("name")==null ? searchHit.getContent().getName():highlightFields.get("name").get(0));
//放到实体类中
result.add(searchHit.getContent());
}
long totalHits = search.getTotalHits();
Stream<SearchHit<DishDtoEs>> searchHitStream = search.get();
List<DishDtoEs> collect = searchHitStream.map(SearchHit::getContent).collect(Collectors.toList());
pageInfo.setRecords(result);
pageInfo.setTotal(totalHits);
return pageInfo;
}