【问题标题】:How does "must" clause with an array of "match" clauses really mean?带有“匹配”子句数组的“必须”子句的真正含义是什么?
【发布时间】:2020-09-15 14:39:31
【问题描述】:

我有一个 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"
  }]
}

这个查询真正是什么意思?

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

进一步,我如何编写一个查询来表达上面列表中的#3,即只有当attrs数组中的单个元素时,文档才应该匹配匹配两个以下条件:

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

【问题讨论】:

  • 你能分享你的映射吗?
  • @OpsterElasticsearchNinja 我是 ES 新手,所以我可能不会掌握一些基本术语。什么是“映射”?
  • @SaurabhNanda,我在您的示例数据上进行了尝试,使用nested 数据类型得到了预期的输出,请参考我的回答。映射是指在 Elasticsearch 中如何对数据进行建模,即使用什么类型的字段,使用什么分析器,您可以将其视为 SQL 的表定义,请参阅elastic.co/guide/en/elasticsearch/reference/current/… 了解更多详细信息。
  • @SaurabhNanda 您是否有机会查看我的答案,如果您需要更多信息,请告诉我。

标签: elasticsearch elasticsearch-query booleanquery


【解决方案1】:

Must 代表"And",因此返回满足匹配查询中所有子句的文档。

必须不满足第 1 点。文档应包含 attrs.name = username 或 attrs.value = johndoe - 您需要一个类似于“OR”的 should 子句

必须满足第 2 点还是第 3 点取决于“attrs”字段的类型。

如果“attr”字段类型为object,则字段将被展平,即在数组的不同字段之间不维护任何关系。因此,如果有 attrs.name="username" 和 attrs.value="John doe",则必须查询将返回一个文档,即使它们不是该数组中同一对象的一部分。

如果你想让数组中的一个对象像一个单独的文档,你需要使用nested字段并使用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

【讨论】:

    【解决方案2】:

    根据您的要求,您需要将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"
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 2012-04-19
      相关资源
      最近更新 更多