天天看点

query_string和minimum_should_match歧义问题1. query_string针对索引不存在字段的处理逻辑变化:2. minimum_should_match歧义3. 继续分析minimum_should_match

1. query_string针对索引不存在字段的处理逻辑变化:

如下DLS:语义为查询此字段(索引内不存在)不包含柔的文档。

{
  "size": 1,
  "track_total_hits": true,
  "_source": "text_content",
  "profile": "true",
  "query": {
    "query_string": {
      "analyzer": "ik_max_word",
      "query": """(NOT("柔"))""",
      "fields": [
        "text_title"
      ]
    }
  }
}
           
  • 因为此字段不存在,所以去除NOT改为此字段包含柔的文档返回结果为0,这里不存在歧义,6.7/7.10版本es返回结果一致。profile API验证均如下:
"type" : "MatchNoDocsQuery",
 "description" : """MatchNoDocsQuery("empty BooleanQuery")""",
           
  • 添加NOT后,因为字段不存在,查询不存在字段不包含柔的文档是返回0?还是理解为对不带NOT的语句取非,返回全部?这里6和7版本表现不同:

    6.7.0版本:

    与不带NOT的结果一致返回0条文档,且profile显示语法也一致

    7.10.2版本:

    做了改变,返回全部文档,profile显示语法添加了一个

    MatchAllDocsQuery(*:*)

    如下图所示。含义大概是NOT语义为不带NOT取非,不带NOT返回0条则NOT应该返回全部?
    query_string和minimum_should_match歧义问题1. query_string针对索引不存在字段的处理逻辑变化:2. minimum_should_match歧义3. 继续分析minimum_should_match

2. minimum_should_match歧义

minimum_should_match

正常理解应该应用于 bool 查询的 should 子句上,来控制最小匹配 should 子句的数量。

默认值(翻译自官网): 如果 bool 查询包含至少一个 should 子句,且无 must 和 fliter 子句,则为1;否则为0。

再说上段中7.10版本查询不存在字段的NOT语句返回为全部文档,默认

minimum_should_match

为0,我们把他改成1:

{
  "size": 1,
  "track_total_hits": true,
  "_source": "text_content",
  "profile": "true",
  "query": {
    "query_string": {
      "analyzer": "ik_max_word",
      "query": """(NOT("柔"))""",
      "fields": [
        "text_title"
      ],
      "minimum_should_match": "1"
    }
  }
}
           

返回结果为0条,而不是之前的全部文档。profile分析如下:

query_string和minimum_should_match歧义问题1. query_string针对索引不存在字段的处理逻辑变化:2. minimum_should_match歧义3. 继续分析minimum_should_match

奇怪的事情发生了,存在MatchAllDocsQuery子句至少满足1子句理论上应该还是返回全部文档,但是却返回了0条?

3. 继续分析minimum_should_match

需要针对正常的 DSL bool 查询和 query_string 的NOT AND OR

等bool查询分别分析minimum_should_match的作用和差异(7.10 版本&针对存在的字段查询)。

3.1. AND

query_string:

"query": """(("柔")AND("脊"))"""
           

dsl bool:

"query": {
  "bool": {
    "must": [
      {
        "match": {
          "text_content": "柔"
        }
      },
      {
        "match": {
          "text_content": "脊"
        }
      }
    ]
  }
}
           

经profile分析两个语句语一致为

+text_content:柔 +text_content:脊

,返回文档数量也一致。由

minimum_should_match

特性可知现在它的值为0,修改为1后:dsl bool 和 query_string 语法解析变为

(+text_content:柔 +text_content:脊)~1

且返回数据条数变为0。

3.2. NOT

query_string:

"query": """(NOT("柔"))"""
           

dsl bool:

"query": {
  "bool": {
    "must_not": [
      {
        "match": {
          "text_content": "柔"
        }
      }
    ]
  }
}
           

经profile分析两个语句语一致如下图,返回文档数量也一致。

query_string和minimum_should_match歧义问题1. query_string针对索引不存在字段的处理逻辑变化:2. minimum_should_match歧义3. 继续分析minimum_should_match

minimum_should_match

特性可知现在它的值为0,修改为1后:

dsl bool语义和返回结果没有发生变化;

query_string返回结果为0,且语义变为下图:

query_string和minimum_should_match歧义问题1. query_string针对索引不存在字段的处理逻辑变化:2. minimum_should_match歧义3. 继续分析minimum_should_match

在这里 query_string 和 dsl bool 的语义产生差异。

3.3 OR

query_string:

"query": """(("柔")OR("脊"))"""
           

dsl bool:

"query": {
  "bool": {
    "should": [
      {
        "match": {
          "text_content": "柔"
        }
      },
      {
        "match": {
          "text_content": "脊"
        }
      }
    ]
  }
}
           

minimum_should_match

特性可知现在它的值应该为1,经测试:

当它的值设置为0时:语义为

text_content:柔 text_content:脊

当它的值设置为1时:语义为

(text_content:柔 text_content:脊)~1

且不设置它的值时为0语义,即默认值为0。query_string 和 dsl bool 在此场景下语义和返回结果一致。包括设置为2时,语义转变为

(text_content:柔 text_content:脊)~2

等同于must语义。

**综上:**在

AND

NOT

的情境下

minimum_should_match

均出现异常,只有在

should

下表现正常。

//TODO

AND OR NOT 组合使用以及minimum_should_match异常原因分析…

继续阅读