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应该返回全部?
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分析如下:
奇怪的事情发生了,存在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分析两个语句语一致如下图,返回文档数量也一致。
由minimum_should_match
特性可知现在它的值为0,修改为1后:
dsl bool语义和返回结果没有发生变化;
query_string返回结果为0,且语义变为下图:
在这里 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异常原因分析…