一、常用查询关键字
1. match 查询
match查询会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。
{ "match": { "name": "南山" }}
QueryBuilders.matchQuery("name", "南山") #java代码
2.match_phrase
默认使用 match_phrase 时会精确匹配查询的短语,需要全部单词和顺序要完全一样,标点符号除外。
{"query":{"match_phrase":{"sign": "好烦恼"}}}
QueryBuilders.matchPhraseQuery(“sign”,"好烦恼")
3.match_phrase_prefix
match_phrase_prefix 和 match_phrase 用法是一样的,区别就在于它允许对最后一个词条前缀匹配。
{"query":{"match_phrase_prefix":{"sign": "我就"}}}
QueryBuilders.matchPhrasePrefixQuery("sign","我就")
4. multi_match 查询
multi_match 查询可以在多个字段上执行相同的 match 查询
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
QueryBuilders.multiMatchQuery("full text search","body","title"); //前一个参数为要查询的数据,后面的为属性名
5.range 查询
range 查询找出那些落在指定区间内的数字或者时间:
{
"range": {
"age": {
"gte": 20, #gt 大于 gte 大于等于
"lt": 30 #lt 小于 lte 小于等于
}
}
}
QueryBuilders.rangeQuery("age").gte(20).lt(30)
6.term 查询
term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:
{ "term": { "age":26}}
{ "term": {"date":"2014-09-01"}}
{ "term": { "sign": "英雄"}}
{ "term": { "tag": "full_text"}}
QueryBuilders.termQuery("sign", "英雄")
7.terms 查询
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
QueryBuilders.termsQuery("sign","英雄","烦恼");
8.exists 查询和 missing 查询
exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:
{"exists": {"field": "title"}}
QueryBuilders.existsQuery("title");
二、组合多查询
bool (布尔)过滤器。 这是个 复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合。
1.must
文档 必须must 匹配这些条件才能被包含进来,与 AND 等价。
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.termQuery("sign", "英雄"))
2.must_not
文档 必须不 must_not 匹配这些条件才能被包含进来,与 NOT 等价。
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.mustNot(QueryBuilders.termQuery("sign", "英雄"))
3.should
至少有一个语句要匹配,与 OR 等价
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.should(QueryBuilders.termQuery("sign", "英雄"))
4.filter
必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.filter(QueryBuilders.termQuery("sign", "英雄"))
三、分页和排序
-
分页检索,可以通过size和from来实现,size返回的条数,默认是10条,from返回的开始。
-
排序,可以根据sort来实现,该字段可以指定索引字段,也可以指定返回结果中的其他字段。
{
"query":{
"match_all":{}
},
"from":1,
"size":10,
"sort": {
"age":"desc",
"money":"asc"
}
}
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("money").order(SortOrder.ASC))
.withPageable(PageRequest.of(1, 10))
.build();
四、高亮highlight
1.只有一个字段需要高亮且不需要自定义标签使用默认标签<em></em>
{
"query": {"match": {"sign": "烦恼"}},
"highlight": {
"fields": {
"sign": {}
}
}
}
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("sign", "烦恼"))
.withHighlightBuilder(new HighlightBuilder().field("sign"))
.build();
SearchHits<Stu> search = esTemplate.search(searchQuery, Stu.class);
List<Stu> stus = new ArrayList<>();
for (SearchHit<Stu> searchHit : search) {
Stu stu = searchHit.getContent();
List<String> nameList = searchHit.getHighlightField("sign");
if (nameList.size() > 0) {
String name_high = nameList.get(0);
//该静态方法作用是根据属性field,拿到stu实例中对应该属性的set方法,并把值name_high到对象stu中
MethodReflectUtil.setValue(stu, field, name_high);
}
stus.add(stu);
}
return stus;
2.只有一个字段需要高亮且需要自定义标签
{
"query": {"match": {"sign": "烦恼"}},
"highlight": {
"pre_tags": [ "<fannao>"],
"post_tags": ["</fannao>"],
"fields": {
"sign": {}
}
}
}
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("sign", "烦恼"))
.withHighlightBuilder(new HighlightBuilder().field("sign").preTags("<fannao>").postTags("</fannao>"))
.build();
SearchHits<Stu> search = esTemplate.search(searchQuery, Stu.class);
List<Stu> stus = new ArrayList<>();
for (SearchHit<Stu> searchHit : search) {
Stu stu = searchHit.getContent();
List<String> nameList = searchHit.getHighlightField("sign");
if (nameList.size() > 0) {
String name_high = nameList.get(0);
//该静态方法作用是根据属性field,拿到stu实例中对应该属性的set方法,并把值name_high到对象stu中
MethodReflectUtil.setValue(stu, field, name_high);
}
stus.add(stu);
}
return stus;
3.有多个字段需要高亮且需要同一个自定义标签
{
"query": {
"bool": {
"must": [
{"match": {"sign": "烦恼"}},
{"term": {"description": "na"}}
]
}
},
"highlight": {
"pre_tags": [ "<fannao>"],
"post_tags": ["</fannao>"],
"fields": {
"sign": {},
"description":{}
}
}
}
List<HighlightBuilder.Field> lst = new ArrayList<>();
HighlightBuilder.Field highlightFields = new HighlightBuilder.Field("sign");
highlightFields.preTags("<fannao>").postTags("</fannao>");
lst.add(highlightFields);
HighlightBuilder.Field highlightFields2 = new HighlightBuilder.Field("description");
highlightFields2.preTags("<fannao>").postTags("</fannao>");
lst.add(highlightFields2);
HighlightBuilder.Field[] ary = new HighlightBuilder.Field[lst.size()];
for (int i = 0; i < lst.size(); i++) {
ary[i] = lst.get(i);
}
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.matchQuery("sign", "烦恼"))
.must(QueryBuilders.termQuery("description", "na"));
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withHighlightFields(ary)
.build();
SearchHits<Stu> search = esTemplate.search(searchQuery, Stu.class);
List<Stu> stus = new ArrayList<>();
for (SearchHit<Stu> searchHit : search) {
Stu stu = searchHit.getContent();
List<String> nameList = searchHit.getHighlightField("sign");
if (nameList.size() > 0) {
String name_high = nameList.get(0);
MethodReflectUtil.setValue(stu, "sign", name_high);
}
List<String> nameList2 = searchHit.getHighlightField("description");
if (nameList2.size() > 0) {
String name_high = nameList2.get(0);
MethodReflectUtil.setValue(stu, "description", name_high);
}
stus.add(stu);
}
4.多个字段高亮且各个字段标签不同
{
"query": {
"bool": {
"must": [
{"match": {"description": "na"}},
{"match": {"sign": "烦恼"}}
]
}
},
"highlight": {
"fields": {
"description": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"]
},
"sign": {
"pre_tags": ["<emm>"],
"post_tags": ["</emm>"]
}
}
}
}
具体代码见第三种,只需将自定义标签换成不同的标签即可。
五、组合多查询、分页、排序、高亮示例
示例: 下面的查询用于查找 age
字段中 20<=age<30
并且 sign
字段中不包含 烦恼
的文档。那些sign
字段被标识为 随便
或时间在2014-01-01之后的的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高。返回第0页,默认30条,根据age字段进行倒叙排序,并且高亮显示sign中随便
字段
{
"query": {
"bool": {
"must": [{"range": { "age": { "gte": 20, "lt": 30 } }}],
"should": [
{ "match": {"sign": "随便"}},
{ "range": { "date": { "gte": "2014-01-01" }}}
],
"must_not": [{"term": {"sign": "烦恼"}}]
}
},
"from": 0,
"size": 30,
"sort": { "age": "desc"},
"highlight": {
"fields": {
"sign": {
"pre_tags": ["<emm>"],
"post_tags": ["</emm>"]
}
}
}
}
BoolQueryBuilder shouldBuilder = QueryBuilders.boolQuery();
shouldBuilder.should(QueryBuilders.matchQuery("sign","随便"))
.should(QueryBuilders.rangeQuery("date").gte("2014-01-01"));
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.rangeQuery("age").gte(20).lt(30))
.mustNot(QueryBuilders.termQuery("sign","烦恼"))
.must(shouldBuilder);
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
.withHighlightBuilder(new HighlightBuilder().field("sign").preTags("<emm>").postTags("</emm>"))
.withPageable(PageRequest.of(0, 30))
.build();
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder) .build();
SearchHits<Stu> search = esTemplate.search(searchQuery, Stu.class);
List<Stu> stus = new ArrayList<>();
for (SearchHit<Stu> searchHit : search) {
Stu stu = searchHit.getContent();
List<String> nameList = searchHit.getHighlightField("sign");
if (nameList.size() > 0) {
String name_high = nameList.get(0);
MethodReflectUtil.setValue(stu, "sign", name_high);
}
stus.add(stu);
}
上面情况中出现了must和should共用的情况,这时should会出现不生效情况,为了避免这种情况的发生,可以采用上面的方式,即:
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery();
shouldQuery.should(QueryBuilders.matchQuery("sign","随便"))
.should(QueryBuilders.rangeQuery("date").gte("2014-01-01"));
queryBuilder.must(QueryBuilders.rangeQuery("age").gte(20).lt(30))
.mustNot(QueryBuilders.termQuery("sign","烦恼"))
.must(shouldBuilder);