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

Pat*_*ski 7 elasticsearch

假设,在ElasticSearch 5中,我有嵌套数据:

{"number":1234, "names": [ 
  {"firstName": "John", "lastName": "Smith"}, 
  {"firstName": "Al", "lastName": "Jones"}
]},  
...
Run Code Online (Sandbox Code Playgroud)

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

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

{ "query" : { "bool": { "filter":[
    { "term": { "number":1234} },
    ????  something with "lastName": "Jones" ????
] } } }
Run Code Online (Sandbox Code Playgroud)

我想回来:

hits: [
   {"number":1234, "names": [ 
     {"firstName": "Al", "lastName": "Jones"}
   ]},  
   ...
]
Run Code Online (Sandbox Code Playgroud)

Tar*_*hut 14

hitssection返回一个_source- 这与你索引的文档完全相同,并且不可能只得到它的一部分.
你是对的,嵌套查询过滤顶级结果,但是inner_hits它会显示哪些内部嵌套对象导致返回这些顶级文档,这正是你需要的.

{
   "query":{
      "bool":{
         "must":[
            {
               "term":{
                  "number":{
                     "value":"1234"
                  }
               }
            },
            {
               "nested":{
                  "path":"names",
                  "query":{
                     "term":{
                        "names.lastName":"Jones"
                     }
                  },
                  "inner_hits":{
                  }
               }
            }
         ]
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

所以现在仍然会返回顶级文档,但是您还有其他inner_hits部分,其中包含匹配的名称.
您应该将嵌套对象视为顶级文档的一部分.如果你真的需要它们分开 - 考虑父/子关系.


小智 5

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

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

             ]
          }
       }
    }
Run Code Online (Sandbox Code Playgroud)