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", "华美达", "皇冠假日"));
  2. 方案二:将should查询对象设置到must方法中
    1
    2
    3
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    boolQuery.must(QueryBuilders.termQuery("city", "上海"))
    .must(QueryBuilders.termsQuery("brand", "华美达", "皇冠假日"));