【问题标题】:matching all nested objects with elasticsearch使用 elasticsearch 匹配所有嵌套对象
【发布时间】:2020-02-20 08:30:47
【问题描述】:

有没有办法让 elasticsearch 只返回 all 其嵌套对象与某些条件匹配的文档?假设我有以下人为的例子:

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

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

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


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

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

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

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

肯定有更好的方法吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    为什么不使用must_not 子句。如果我是你,我会在带有 must_not 子句的 bool 过滤器中搜索拥有 5 岁以上宠物的人,以搜索拥有 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 岁或以下的人,从而获得所需的结果。

    祝你好运!

    【讨论】:

    • 这适用于我只搜索一个年龄范围(明显相反)的特殊情况,但我想如果我想搜索其他更复杂的字段,我可以把它包装起来在not 过滤器中,在bool 过滤器的must_not 部分中。我会稍等一下,看看其他人是否有替代解决方案,否则我认为这个答案有效。谢谢!
    • 是的,我想你可以这样做。 bool 过滤器组合也非常有效,因为它们适用于按位运算。看看this interesting article on bool vs and and or filters
    • 在范围查询(相对于“gte”)的上下文中,“from”是什么意思?我似乎找不到任何文档。
    • @JoshReback from 是当前 gt 的弃用语法。
    猜你喜欢
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    相关资源
    最近更新 更多