解决ES中同时使用must和should 只有must生效的问题
错误示例
- DSL语句版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"city": {
"value": "上海"
}
}
}
],
"should": [
{"term": {
"brand": {
"value": "希尔顿"
}
}},
{"term": {
"brand": {
"value": "皇冠假日"
}
}}
]
}
},
"size": 100
} - JavaAPI版
1
2
3BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.should(QueryBuilders.termsQuery("brand", "希尔顿", "皇冠假日")); - 布尔查询中,使用should属性时,生效了,但没完全生效。
- 查到的结果集中包含了
上海希尔顿
和上海皇冠假日
的酒店文档,但是后面还出现了其他品牌的酒店文档 - 利用控制变量法,成功找到bug原因
- 单独使用
must
查询,没有问题 - 单独使用
should
查询,没有问题 - 联合使用
must
和should
,查询到的结果条数,与单独使用must
一样。但是排序是优先展示符合should
条件的文档
- 单独使用
失效原因
- should在和must同时使用的时候es内部属性
minumum_should_match
默认是 0 - 单独使用should时
minumum_should_match
默认是 1
解决方案
- 方案一:为
minumum_should_match
手动赋值1
2
3
4BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.minimumShouldMatch(1);
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.should(QueryBuilders.termsQuery("brand", "华美达", "皇冠假日")); - 方案二:将should查询对象设置到must方法中
1
2
3BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.must(QueryBuilders.termsQuery("brand", "华美达", "皇冠假日"));
评论