一、常用查询关键字

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);   
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐