在Elasticsearch中搜索具有与给定查询匹配的所有嵌套子项的对象

时间:2015-01-20 11:07:47

标签: elasticsearch

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

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

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

例如,假设我想检索具有" key"的所有子项的所有实例。 ="是"。 鉴于以下情况:

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

我想只检索第一个(" id" =" 1")。

对我来说,使用过滤器或查询都很好。 我已经尝试使用" not filter"和#34; must_not bool filter"。我们的想法是使用双重否定来仅提取不具有与给定字段不同的字段的对象。 但是,我无法正确写下此查询。

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

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

编写此查询

更新

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

我也感兴趣的是你不知道你想要避免的值,你只想将嵌套对象与" key" =" yes"

2 个答案:

答案 0 :(得分:2)

您需要一个扁平化的数据结构 - 一组值。最简单的方法是不要过多地更改当前映射,而是使用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"
            }
          }
        }
      }
    }
  }
}

查询保持不变。

答案 1 :(得分:0)

遇到了同样的问题,尽管没有只是/否的变体。 根据克林顿·戈姆利在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"
              }
            }
          }
        }
      ]
    }
  }
}