布爾查詢是常用的復合查詢,它把多個子查詢組合成一個布爾表達式。布爾查詢可以按照各個子查詢的具體匹配程度對文檔進行打分計算。
1.must查詢
當查詢中包含must查詢時,相當於邏輯查詢中的“與”查詢。命中的文檔必須匹配該子查詢的結果,並且ES會將該子查詢與文檔的匹配程度值加入總得分里。must搜索包含一個數組,可以把其他的term級別的查詢及布爾查詢放入其中。
示例:
GET /hotel/_search { "query": { "bool": { "must": [ //must查詢,數組內可封裝各類子查詢 { //第一個子查詢:城市為北京 "term": { "city": { "value": "北京" } } }, { //第二個子查詢:價格>=350且價格<=400 "range": { "price": { "gte": 350, "lte": 400 } } } ] } } }
在Java客戶端上構建must搜索時,可以使用QueryBuilders.boolQuery().must()進行構建,上面的range查詢例子改寫成Java客戶端請求的形式為:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //構建城市term查詢 TermQueryBuilder termQueryIsReady = QueryBuilders.termQuery("city", "北京"); RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").gte(350).lte(600); //構建價格range查詢 //進行關系“與”查詢 boolQueryBuilder.must(termQueryIsReady).must(rangeQueryBuilder); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder); //設置查詢
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
2.should查詢
當查詢中包含should查詢時,表示當前查詢為“或”查詢。命中的文檔可以匹配該查詢中的一個或多個子查詢的結果,並且ES會將該查詢與文檔的匹配程度加入總得分里。should查詢包含一個數組,可以把其他的term級別的查詢及布爾查詢放入其中。
示例:
GET /hotel/_search { "query": { "bool": { "should": [ //shoud查詢,數組內可封裝各類子查詢 { //第一個子查詢:城市為北京 "term": { "city": { "value": "北京" } } }, { //第二個子查詢:城市為天津 "term": { "city": { "value": "天津" } } } ] } } }
在Java客戶端上構建should搜索時,可以使用QueryBuilders.boolQuery().should()進行構建,上面的例子改寫成Java客戶端請求的形式為:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //構建城市為“北京”的term查詢 TermQueryBuilder termQueryIsReady = QueryBuilders.termQuery("city", "北京"); //構建城市為“上海”的term查詢 TermQueryBuilder termQueryWritter = QueryBuilders.termQuery("city", "上海"); //進行關系“或”查詢 boolQueryBuilder.should(termQueryIsReady).should(termQueryWritter); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder); //設置查詢
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
3.must not查詢
當查詢中包含must not查詢時,表示當前查詢為“非”查詢。命中的文檔不能匹配該查詢中的一個或多個子查詢的結果,ES會將該查詢與文檔的匹配程度加入總得分里。must not查詢包含一個數組,可以把其他term級別的查詢及布爾查詢放入其中。
示例:
GET /hotel/_search { "query": { "bool": { "must_not": [ // must_not查詢,數組內可封裝各類子查詢 { //第一個子查詢:城市為北京 "term": { "city": { "value": "北京" } } }, { //第二個子查詢:城市為天津 "term": { "city": { "value": "天津" } } } ] } } }
在Java客戶端上構建must_not搜索時,可以使用QueryBuilders.boolQuery().mustNot()方法進行構建,上面的例子改寫成Java客戶端請求的形式為:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //構建城市為“北京”的term查詢 TermQueryBuilder termQueryIsReady = QueryBuilders.termQuery("city", "北京"); //構建城市為“天津”的term查詢 TermQueryBuilder termQueryWritter = QueryBuilders.termQuery("city", "天津"); //進行關系“必須不”查詢 boolQueryBuilder.mustNot(termQueryIsReady).mustNot(termQueryWritter); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder); //設置查詢
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
4.filter查詢
filter查詢即過濾查詢,該查詢是布爾查詢里非常獨特的一種查詢。其他布爾查詢關注的是查詢條件和文檔的匹配程度,並按照匹配程度進行打分;而filter查詢關注的是查詢條件和文檔是否匹配,不進行相關的打分計算,但是會對部分匹配結果進行緩存。
示例:
GET /hotel/_search { "query": { "bool": { "filter": [ // filter查詢,數組內可封裝各類子查詢 { //第一個子查詢:城市為北京 "term": { "city": "北京" } }, { //第一個子查詢:滿房狀態為否 "term": { "full_room": false } } ] } } }
在Java客戶端上構建filter搜索時,可以使用QueryBuilders.boolQuery().filter()進行構建,上面的例子改寫成Java客戶端請求的形式為:
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.filter(QueryBuilders.termQuery("city", "青島")); boolQueryBuilder.filter(QueryBuilders.termQuery("full_room", true)); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
使用filter查詢的子句是不計算分數的,這可以減少不小的時間開銷。
為提升查詢效率,對於簡單的term級別匹配查詢,應該根據自己的實際業務場景選擇合適的查詢語句,需要確定這些查詢項是否都需要進行打分操作,如果某些匹配條件不需要打分操作的話,那么應該把這些查詢全部改成filter形式,讓查詢更高效。
文章來源:Elasticsearch搜索引擎構建入門與實戰 --> 4.2.3 布爾查詢