【问题标题】:Searching objects having all nested children matching a given query in Elasticsearch在 Elasticsearch 中搜索具有与给定查询匹配的所有嵌套子级的对象
【发布时间】:2019-03-15 02:15:08
【问题描述】:

给定一个具有以下映射的对象:

{
    "a": {
        "properties": {
            "id": {"type": "string"}
            "b": {
                "type": "nested",
                "properties": {
                    "key": {"type": "string"}
                }
            }
        }
    }
}

我想检索该对象的所有实例,该对象的所有嵌套子项都与给定查询匹配。

例如,假设我想检索所有具有“key”=“yes”的孩子的所有实例。 鉴于以下情况:

{
    "id": "1",
    "b": [
        {
            "key": "yes"
        },
        {
            "key": "yes"
        }
    ] 
},
{
    "id": "2",
    "b": [
        {
            "key": "yes"
        },
        {
            "key": "yes"
        },
        {
            "key": "no"
        }
    ] 
},

我只想检索第一个(“id”=“1”的那个)。

对我来说,使用过滤器或查询都可以。 我已经尝试使用“not filter”和“must_not bool filter”。这个想法是使用双重否定来仅提取没有与给定字段不同的字段的对象。 但是,我无法正确写下此查询。

我意识到这不是搜索引擎的常见查询,但就我而言,它可能很有用。

是否可以使用嵌套对象编写此查询(“forall 嵌套查询”)? 如果不是,是否可以使用父子编写此查询?

更新

Andrei Stefan 给出了一个很好的答案,以防我们知道我们想要避免的所有“key”值(在示例中为“no”)。

如果您不知道要避免的值,并且只想将嵌套对象与“key”="yes" 匹配,我也很感兴趣。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    为此,您需要一个扁平的数据结构 - 一个值数组。最简单且不过多更改当前映射的方法是使用 include_in_parent 属性并查询父项中包含的字段以满足此特定要求:

    {
      "mappings": {
        "a": {
          "properties": {
            "id": {
              "type": "string"
            },
            "b": {
              "type": "nested",
              "include_in_parent": true,
              "properties": {
                "key": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
    

    然后您的查询将如下所示:

    {
      "query": {
        "filtered": {
          "filter": {
            "and": [
              {
                "query": {
                  "query_string": { "query": "b.key:(yes NOT no)"}
                }
              }
            ]
          }
        }
      }
    }
    

    另一种方法是将字段的类型从nested 更改为object,但这样您将失去使用nested 字段的优势:

    {
      "mappings": {
        "a": {
          "properties": {
            "id": {
              "type": "string"
            },
            "b": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
    

    查询保持不变。

    【讨论】:

    • 感谢您的回答,它回答了我的问题。有没有办法表达查询,这样我就不需要明确告诉我不想包含的字段?例如,假设我想过滤所有带有“key”="yes" 的对象,但我不知道“key”可以具有的其他值。
    • 这很难。我没有解决办法。
    • 我会更新这个问题,看看是否有人对此有解决方案会很有趣。
    【解决方案2】:

    遇到了同样的问题,虽然没有只是是/否变体。 根据 Clinton Gormley 在https://github.com/elastic/elasticsearch/issues/19166 中的回答: “你不能以任何有效的方式做到这一点。你必须计算所有孩子并将其与匹配的孩子数量进行比较。以下将返回所有孩子匹配的所有父母,但这是一个非常低效的解决方案,我永远不会推荐使用它在实践中”:

    {
      "query": {
        "bool": {
          "must": [
            {
              "nested": {
                "path": "b",
                "score_mode": "sum",
                "query": {
                  "function_score": {
                    "query": {
                      "match_all": {}
                    },
                    "functions": [
                      {
                        "weight": -1
                      },
                      {
                        "filter": {
                          "match": {
                            "b.key": "yes"
                          }
                        },
                        "weight": 1
                      }
                    ],
                    "score_mode": "sum",
                    "boost_mode": "replace"
                  }
                }
              }
            }
          ]
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-18
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多