天天看點

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異常原因分析…

繼續閱讀