预售网站开发,wordpress繁体版,网络营销费用预算,广州市城市建设档案馆网站使用QueryBuilders、NativeSearchQuery实现复杂查询
本文继续前面文章《ElasticSearch系列#xff08;二#xff09;springboot中集成使用ElasticSearch的Demo》#xff0c;在前文中#xff0c;我们介绍了使用springdata做一些简单查询#xff0c;但是要实现一些高级的组…使用QueryBuilders、NativeSearchQuery实现复杂查询
本文继续前面文章《ElasticSearch系列二springboot中集成使用ElasticSearch的Demo》在前文中我们介绍了使用springdata做一些简单查询但是要实现一些高级的组合等查询还是需要使用ES的一些原生方法。
本文介绍一些高级查询用法。需要看环境搭建的先直接看前文。
数据准备 es中事先插入了20多条数据用于测试然后title和content使用了ik_smart分词
一、ElasticsearchRestTemplate
ElasticsearchRestTemplate是Spring封装ES客户端的一些原生api模板方便实现一些查询和ElasticsearchTemplate一样但是目前spring推荐使用前者是一种更高级的REST风格api。
废话不多说先上一个demo
RunWith(SpringRunner.class)
SpringBootTest
public class EsArticleControllerTest {Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;Testpublic void test1() {NativeSearchQuery nativeSearchQuery new NativeSearchQueryBuilder()//查询条件.withQuery(QueryBuilders.queryStringQuery(浦东开发开放).defaultField(title))//分页.withPageable(PageRequest.of(0, 5))//排序.withSort(SortBuilders.fieldSort(id).order(SortOrder.DESC))//高亮字段显示.withHighlightFields(new HighlightBuilder.Field(浦东)).build();ListArticleEntity articleEntities elasticsearchRestTemplate.queryForList(nativeSearchQuery, ArticleEntity.class);articleEntities.forEach(item - System.out.println(item.toString()));}
}这个方法是根据指定的title模糊查询一个列表其中用到了几个关键类说明一下
elasticsearchRestTemplate.queryForList是查询一个列表用的就是ElasticsearchRestTemplate的一个对象实例
NativeSearchQuery 是springdata中的查询条件
NativeSearchQueryBuilder 用于建造一个NativeSearchQuery查询对象
QueryBuilders 设置查询条件是ES中的类
SortBuilders 设置排序条件
HighlightBuilder 设置高亮显示下面分类具体介绍下。
二、NativeSearchQuery
这是一个原生的查询条件类用来和ES的一些原生查询方法进行搭配实现一些比较复杂的查询。
下面是NativeSearchQuery的一些内部属性基本上都是ES的一些内部对象
//查询条件查询的时候会考虑关键词的匹配度并按照分值进行排序
private QueryBuilder query;
//查询条件查询的时候不考虑匹配程度以及排序这些事情
private QueryBuilder filter;
//排序条件的builder
private ListSortBuilder sorts;
private final ListScriptField scriptFields new ArrayList();
private CollapseBuilder collapseBuilder;
private ListFacetRequest facets;
private ListAbstractAggregationBuilder aggregations;
//高亮显示的builder
private HighlightBuilder highlightBuilder;
private HighlightBuilder.Field[] highlightFields;
private ListIndexBoost indicesBoost;上述属性的值就像demo的写的通过NativeSearchQueryBuilder进行构建即可最终作为elasticsearchRestTemplate的查询条件入参。
三、QueryBuilders
QueryBuilders是ES中的查询条件构造器。下面结合一些具体的查询场景分析其常用方法。
ES中已经有title为 “***关心浦东开发开放” 的数据
ik_smart分词结果
{
tokens: [
{
token: ***,
start_offset: 3,
end_offset: 6,
type: CN_WORD,
position: 1
},
{
token: 关心,
start_offset: 6,
end_offset: 8,
type: CN_WORD,
position: 2
},
{
token: 浦东,
start_offset: 8,
end_offset: 10,
type: CN_WORD,
position: 3
},
{
token: 开发,
start_offset: 10,
end_offset: 12,
type: CN_WORD,
position: 4
},
{
token: 开放,
start_offset: 12,
end_offset: 14,
type: CN_WORD,
position: 5
}
]
}3.1精确查询
精确指的是查询关键字或者关键字分词后必须与目标分词结果完全匹配。
1.指定字符串作为关键词查询关键词支持分词
//查询title字段中包含 ”开发”、“开放 这个字符串的document相当于把浦东开发开放分词了再查询 QueryBuilders.queryStringQuery(“开发开放”).defaultField(“title”); //不指定feild查询范围为所有feild QueryBuilders.queryStringQuery(“青春”); //指定多个feild QueryBuilders.queryStringQuery(“青春”).field(“title”).field(“content”);
2.以关键字“开发开放”关键字不支持分词
QueryBuilders.termQuery(“title”, “开发开放”) QueryBuilders.termsQuery(“fieldName”, “fieldlValue1”,“fieldlValue2…”)
3.以关键字“开发开放”关键字支持分词
QueryBuilders.matchQuery(“title”, “开发开放”) QueryBuilders.multiMatchQuery(“fieldlValue”, “fieldName1”, “fieldName2”, “fieldName3”)
3.2 模糊查询
模糊是指查询关键字与目标关键字可以模糊匹配。
1.左右模糊查询其中fuzziness的参数作用是在查询时es动态的将查询关键词前后增加或者删除一个词然后进行匹配
QueryBuilders.fuzzyQuery(“title”, “开发开放”).fuzziness(Fuzziness.ONE)
2.前缀查询查询title中以“开发开放”为前缀的document
QueryBuilders.prefixQuery(“title”, “开发开放”)
3.通配符查询支持*和表示单个字符注意不建议将通配符作为前缀否则导致查询很慢
QueryBuilders.wildcardQuery(“title”, “开*放”) QueryBuilders.wildcardQuery(“title”, “开放”)
注意 在分词的情况下针对fuzzyQuery、prefixQuery、wildcardQuery不支持分词查询即使有这种doucment数据也不一定能查出来因为分词后不一定有“开发开放”这个词
查询总结
开发开放 放 开 queryStringQuery 目标中含有开发、开放、开发开放的 无 无 matchQuery 同queryStringQuery 无 无 termQuery 无结果因为它不支持分词 无 无 prefixQuery 无结果因为它不支持分词 无 有目标分词中以”开“开头的 fuzzyQuery 无结果但是与fuzziness参数有关系 无 无 wildcardQuery 开发开放无结果 开有 放*无
3.3 范围查询
//闭区间查询 QueryBuilders.rangeQuery(“fieldName”).from(“fieldValue1”).to(“fieldValue2”); //开区间查询默认是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() QueryBuilders.boolQuery() QueryBuilders.boolQuery().must();//文档必须完全匹配条件相当于and QueryBuilders.boolQuery().mustNot();//文档必须不匹配条件相当于not QueryBuilders.boolQuery().should();//至少满足一个条件这个文档就符合should相当于or
具体demo如下
public void testBoolQuery() { NativeSearchQuery nativeSearchQuery new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery() .should(QueryBuilders.termQuery(“title”, “开发”)) .should(QueryBuilders.termQuery(“title”, “青春”)) .mustNot(QueryBuilders.termQuery(“title”, “潮头”)) ) .withSort(SortBuilders.fieldSort(“id”).order(SortOrder.DESC)) .withPageable(PageRequest.of(0, 50)) .build(); List articleEntities elasticsearchRestTemplate.queryForList(nativeSearchQuery, ArticleEntity.class); articleEntities.forEach(item - System.out.println(item.toString())); }
以上是查询title分词中包含“开发”或者“青春”但不能包含“潮头”的document 也可以多个must组合。
四、SortBuilders排序
上述demo中我们使用了排序条件
//按照id字段降序 .withSort(SortBuilders.fieldSort(“id”).order(SortOrder.DESC)) 1 2 注意排序时有个坑就是在以id排序时比如降序结果可能并不是我们想要的。因为根据id排序es实际上会根据_id进行排序但是_id是string类型的排序后的结果会与整型不一致。
建议 在创建es的索引mapping时将es的id和业务的id分开比如业务id叫做myId
Id
Field(type FieldType.Long, store true)
private Long myId;Field(type FieldType.Text, store true, analyzer ik_smart)
private String title;Field(type FieldType.Text, store true, analyzer ik_smart)
private String content;这样后续排序可以使用myId进行排序。
五、分页
使用如下方式分页
Test
public void testPage() {
NativeSearchQuery nativeSearchQuery new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery(title, 青春))
.withSort(SortBuilders.fieldSort(myId).order(SortOrder.DESC))
.withPageable(PageRequest.of(0, 50))
.build();
AggregatedPageArticleEntity page elasticsearchRestTemplate.queryForPage(nativeSearchQuery, ArticleEntity.class);
ListArticleEntity articleEntities page.getContent();
articleEntities.forEach(item - System.out.println(item.toString()));
}注意如果不指定分页参数es默认只显示10条。
六、高亮显示 查询title字段中的关键字并高亮显示
Test
public void test() {String preTag font color#dd4b39;String postTag /font;NativeSearchQuery nativeSearchQuery new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery(title, 开发)).withPageable(PageRequest.of(0, 50)).withSort(SortBuilders.fieldSort(id).order(SortOrder.DESC)).withHighlightFields(new HighlightBuilder.Field(title).preTags(preTag).postTags(postTag)).build();AggregatedPageArticleEntity page elasticsearchRestTemplate.queryForPage(nativeSearchQuery, ArticleEntity.class,new SearchResultMapper() {Overridepublic T AggregatedPageT mapResults(SearchResponse response, ClassT clazz, Pageable pageable) {ListArticleEntity chunk new ArrayList();for (SearchHit searchHit : response.getHits()) {if (response.getHits().getHits().length 0) {return null;}ArticleEntity article new ArticleEntity();article.setMyId(Long.valueOf(searchHit.getSourceAsMap().get(id).toString()));article.setContent(searchHit.getSourceAsMap().get(content).toString());HighlightField title searchHit.getHighlightFields().get(title);if (title ! null) {article.setTitle(title.fragments()[0].toString());}chunk.add(article);}if (chunk.size() 0) {return new AggregatedPageImpl((ListT) chunk);}return null;}Overridepublic T T mapSearchHit(SearchHit searchHit, ClassT type) {return null;}});ListArticleEntity articleEntities page.getContent();
articleEntities.forEach(item - System.out.println(item.toString()));
}结果
title勇立潮头——***关心浦东开发开放40, content外交部望