在ElasticSearch中,如何在结果中过滤嵌套文档?

时间:2017-08-08 14:57:55

标签: elasticsearch

假设在ElasticSearch 5中,我的数据嵌套如下:

{"number":1234, "names": [ 
  {"firstName": "John", "lastName": "Smith"}, 
  {"firstName": "Al", "lastName": "Jones"}
]},  
...

我想查询编号为1234的匹配,但仅返回与“lastName”匹配的名称:“Jones”,以便我的结果省略不匹配的名称。换句话说,我想根据术语查询或类似内容,仅返回匹配文档的一部分

一个简单的嵌套查询不会这样做,因为它会过滤顶级结果。有什么想法吗?

{ "query" : { "bool": { "filter":[
    { "term": { "number":1234} },
    ????  something with "lastName": "Jones" ????
] } } }

我想回来:

hits: [
   {"number":1234, "names": [ 
     {"firstName": "Al", "lastName": "Jones"}
   ]},  
   ...
]

3 个答案:

答案 0 :(得分:11)

hits部分返回_source - 这与您编入索引的文档完全相同,并且只能获取其中的部分内容。
你是对的,嵌套查询过滤顶级结果,但是使用inner_hits它会显示哪些内部嵌套对象导致返回这些顶级文档,这正是你需要的。

{
   "query":{
      "bool":{
         "must":[
            {
               "term":{
                  "number":{
                     "value":"1234"
                  }
               }
            },
            {
               "nested":{
                  "path":"names",
                  "query":{
                     "term":{
                        "names.lastName":"Jones"
                     }
                  },
                  "inner_hits":{
                  }
               }
            }
         ]
      }
   }
}

现在仍然会返回顶级文档,但您还有其他inner_hits部分,其名称与之匹配。
您应该将嵌套对象视为顶级文档的一部分。 如果你真的需要它们分开 - 考虑parent/child relations.

答案 1 :(得分:2)

尝试这样的事情

{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "bool": {
               "must": [
                  {
                     { "term": { "number":1234} }
                  },
                  {
                     "nested": {
                        "path": "something",
                        "filter": {
                           "term": {
                              "something.lastName": "Jones"
                           }
                        },
                        "inner_hits" : {}
                     }
                  }
               ]
            }
         }
      }
   }
}

我使用了这个Refrence

答案 2 :(得分:0)

类似但有点不同,使用should参数,然后查看名称的内部命中。这将返回顶级文档,然后inner_hits将有任何命中。

   { 
      "_source": {
        "excludes": ["names"]
      },
       "query":{
          "bool":{
             "must":[
                {
                   "term":{
                      "number":{
                         "value":"1234"
                      }
                   }
                }
             ],
             should: [
             {
                "nested":{
                   "path":"names",
                   "query":{
                      "term":{
                         "names.lastName":"Jones"
                      }
                   },
                   "inner_hits":{
                   }
                }
             }

             ]
          }
       }
    }