2

有没有办法让 elasticsearch 只返回所有嵌套对象都符合某些条件的文档?假设我有以下人为的例子:

"mappings": {                                                                                                                                                            
  "person": {                                                                                                                                                            
    "properties": {                                                                                                                                                      
      "name": { "type": "string" },                                                                                                                                       
      "other_info": ...                                                                                                                                                  

      "pet": {                                                                                                                                                      
        "type": "nested",                                                                                                                                                 
        "properties": {                                                                                                                                                  
          "gender": { "type": "string" },                                                                                                                                 
          "age": { "type": "integer" },                                                                                                                                   
          "name": { "type": "string" },                                                                                                                                   
          "other_info": ...                                                                                                                                              
        }                                                                                                                                                                
      }                                                                                                                                                                  
    }                                                                                                                                                                    
  }                                                                                                                                                                      
}    

在这种情况下,我将如何搜索拥有所有年龄大于 5 岁的宠物的人?我还想搜索与宠物无关的其他属性,但为简单起见,让我们假设其他属性。如果一个人拥有三只宠物,但其中只有一两只超过 5 岁,我不希望它出现在搜索结果中。


我找不到任何关于如何做到这一点的信息,所以我考虑了一个我不太喜欢的替代解决方案。不要使用嵌套文档,而是使用单独的宠物索引,将人员 ID 作为属性(可能带有_parent字段?)。然后我可以执行以下操作:

  • 搜索5岁以上的宠物,得到宠物列表作为结果
  • 在应用程序端,将列表中的宠物按人员 ID 分组
  • 计算每个组中的宠物数量,如果与此人拥有的宠物总数相匹配,则将人员 ID 添加到列表中
  • 根据 ID 和我要检查的任何其他人员特定属性对人员索引进行另一次搜索

不过,这似乎是一种非常迂回的方式,而且如果我走那条路,我需要在查询人员索引之前知道每个人拥有的宠物总数(比如将其存储为每只宠物的属性,但是这只会让它变得非常混乱)或通过搜索至少有一个匹配宠物的所有人,并将宠物计数提前存储在人员索引中(或使用脚本过滤器?),然后检查计数是否匹配。

我遇到了这个 github 问题(添加了“每次命中返回匹配的嵌套内部对象”功能),这本来非常有用,但不幸的是它还没有实现。

当然有更好的方法来做到这一点?

4

1 回答 1

9

为什么不使用must_not从句。如果我是你,我会在过滤器中搜索拥有 5 岁以上宠物的人,并在一个bool过滤器中must_not搜索拥有 5 岁以下宠物的人。

像这样:

"filter" : {
    "bool" : {
        "must" : {
            "nested" : {
                "path" : "person.pet",
                "filter" : {
                    "range" : {
                        "person.pet.age" : { "from" : 5 }
                    }
                } 
            }
        },
        "must_not" : {
            "nested" : {
                "filter" : {
                    "range" : {
                        "person.pet.age" : { "lte" : 5 }
                    }
                } 
            }
        }
    }
}

我在这里所做的是首先让所有至少有一只 5 岁以上宠物的人(这将包括拥有多只宠物的人,其中一些是年轻的)。然后我排除所有有 5 岁或以下宠物的人,留下理想的结果。

祝你好运!

于 2013-09-18T08:35:29.117 回答