"must" 子句与 "match" 子句数组的真正含义是什么?

How does "must" clause with an array of "match" clauses really mean?

我有一个 elasticsearch query 看起来像这样...

  "query": {
    "bool": {
      "must": [{
        "match": {"attrs.name": "username"}
      }, {
        "match": {"attrs.value": "johndoe"}
      }]
    }
  }

... 索引中的文档如下所示:

{
  "key": "value",
  "attrs": [{
    "name": "username",
    "value": "jimihendrix"
  }, {
    "name": "age",
    "value": 23
  }, {
    "name": "alias",
    "value": "johndoe"
  }]
}

这个查询 really 是什么意思?

  1. 文档应包含 attrs.name = usernameattrs.value = johndoe
  2. 或者,文档应同时包含 attrs.name = usernameattrs.value = johndoe,即使它们可能与 attrs 数组中的 不同元素 匹配(这意味着上面给出的文档将 匹配 查询)
  3. 或者,文档应同时包含 attrs.name = usernameattrs.value = johndoe,但它们必须与 attrs 数组中的 相同元素 相匹配(这意味着上面给出的文档 不匹配 查询)

此外, 我如何编写一个查询来表达上面列表中的#3,即只有 单个元素[=49 时文档才应该匹配=] 在 attrs 数组中匹配 both 以下条件:

  • attrs.name = 用户名
  • attrs.value = johndoe

根据您的要求,您需要将 attrs 字段定义为嵌套,请参阅 nested type in Elasticsearch 了解更多信息。 免责声明:它维护关系但查询成本高。

其他两个问题的答案也取决于您使用的数据类型,请参阅 nested vs object data type 了解更多详情

编辑:使用示例映射、示例文档和预期结果的解决方案

使用嵌套类型的索引映射

{
    "mappings": {
        "properties": {
            "attrs": {
                "type": "nested"
            }
        }
    }
}

索引 2 示例文档,其中一个符合标准,另一个不符合标准

{
    "attrs": [
        {
            "name": "username",
            "value": "johndoe"
        },
        {
            "name": "alias",
            "value": "myname"
        }
    ]
}

另一个服务标准

{
    "attrs": [
        {
            "name": "username",
            "value": "jimihendrix"
        },
        {
            "name": "age",
            "value": 23
        },
        {
            "name": "alias",
            "value": "johndoe"
        }
    ]
}

和搜索查询

{
  "query": {
    "nested": {
      "path": "attrs",
      "inner_hits": {}, 
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "attrs.name": "username"
              }
            },
            {
              "match": {
                "attrs.value": "johndoe"
              }
            }
          ]
        }
      }
    }
  }
}

和搜索结果

 "hits": [
            {
                "_index": "nested",
                "_type": "_doc",
                "_id": "2",
                "_score": 1.7509375,
                "_source": {
                    "attrs": [
                        {
                            "name": "username",
                            "value": "johndoe"
                        },
                        {
                            "name": "alias",
                            "value": "myname"
                        }
                    ]
                },
                "inner_hits": {
                    "attrs": {
                        "hits": {
                            "total": {
                                "value": 1,
                                "relation": "eq"
                            },
                            "max_score": 1.7509375,
                            "hits": [
                                {
                                    "_index": "nested",
                                    "_type": "_doc",
                                    "_id": "2",
                                    "_nested": {
                                        "field": "attrs",
                                        "offset": 0
                                    },
                                    "_score": 1.7509375,
                                    "_source": {
                                        "name": "username",
                                        "value": "johndoe"
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        ]

必须代表"And"所以满足匹配查询中所有子句的文档是returned .

必须不满足第 1 点。文档应包含 attrs.name = 用户名或 attrs.value = johndoe- 您需要一个 should 子句,其工作方式类似于 "OR"

Must 是否满足第 2 点或第 3 点取决于 "attrs" 字段的类型。

如果 "attr" 字段类型是 object 则字段被展平,即数组的不同字段之间没有关系。因此,如果有 attrs.name="username" 和 attrs.value="John doe",则必须查询 return 文档,即使它们不是该数组中同一对象的一部分。

如果你想让一个数组中的对象像一个单独的文档一样,你需要使用nested field and use nested query来匹配文档

{
  "query": {
    "nested": {
      "path": "attrs",
      "inner_hits": {}, --> returns matched nested documents
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "attrs.name": "username"
              }
            },
            {
              "match": {
                "attrs.value": "johndoe"
              }
            }
          ]
        }
      }
    }
  }
}

响应中的命中将包含所有嵌套文档,要获取所有匹配的嵌套文档,必须指定 inner_hits