ES版本:7.12.1

错误示例

  • 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
29
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"city": {
"value": "上海"
}
}
}
],
"should": [
{"term": {
"brand": {
"value": "希尔顿"
}
}},
{"term": {
"brand": {
"value": "皇冠假日"
}
}}
]
}
},
"size": 100
}
  • JavaAPI版
1
2
3
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.should(QueryBuilders.termsQuery("brand", "希尔顿", "皇冠假日"));
  • 布尔查询中,使用should属性时,生效了,但没完全生效。
  • 查到的结果集中包含了上海希尔顿上海皇冠假日的酒店文档,但是后面还出现了其他品牌的酒店文档
  • 利用控制变量法,成功找到bug原因
    • 单独使用must查询,没有问题
    • 单独使用should查询,没有问题
    • 联合使用mustshould,查询到的结果条数,与单独使用must一样。但是排序是优先展示符合should条件的文档

失效原因

  • should在和must同时使用的时候es内部属性minumum_should_match默认是 0
  • 单独使用should时minumum_should_match默认是 1

解决方案

  1. 方案一:为minumum_should_match手动赋值
1
2
3
4
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.minimumShouldMatch(1);
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.should(QueryBuilders.termsQuery("brand", "华美达", "皇冠假日"));
  1. 方案二:将should查询对象设置到must方法中
1
2
3
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("city", "上海"))
.must(QueryBuilders.termsQuery("brand", "华美达", "皇冠假日"));