Elasticsearch嵌套过滤器具有包容性和排他性

时间:2014-10-31 01:10:12

标签: elasticsearch

我有一个对象映射,它以类似标签的方式使用嵌套对象(在我们的示例中为props)。 每个标记都属于客户端/用户,并且我们希望允许用户针对query_string生成props.name样式搜索。

问题在于,当我们运行查询时,如果一个对象有多个道具,并且当其他人不知道该对象返回时,其中一个道具匹配过滤器,当我们想要相反时 - 如果一个返回false don& #39; t返回vs.如果一个返回真实的回报。

我在这里发布了一个全面的例子:https://gist.github.com/d2kagw/1c9d4ef486b7a2450d95

提前致谢。

1 个答案:

答案 0 :(得分:1)

我相信你可能需要一个扁平的值列表的优势,比如值数组。数组和嵌套对象之间的主要区别在于后者"知道"嵌套属性的哪个值对应于相同嵌套对象中另一个属性的另一个值。另一方面,值数组会使某个属性的值变平并且会失去"关联"在client_idname之间。意思是,对于数组,您有props.client_id = [null, 2]props.name = ["petlover", "premiumshopper"]

使用nested过滤器,您希望将该字符串与props.name的所有值匹配,这意味着所有一个父文档的嵌套props.name需要匹配。好吧,嵌套对象不会发生这种情况,因为嵌套文档是分开的并且是单独查询的。并且,如果至少有一个嵌套文档匹配,那么它被视为匹配。

换句话说,对于像"query": "props.name:(carlover NOT petlover)"这样的查询,你基本上需要针对一个扁平的值列表运行它,就像数组一样。您需要针对[" carlover"," petlover"]运行该查询。

我的建议是制作嵌套文档"include_in_parent": true(意思是,在父级中保留一个扁平的,类似数组的值列表)并更改一下查询:

  • 对于query_string部分,使用展平属性方法,以便能够将您的查询与元素的组合列表进行匹配,而不是逐个元素。
  • 代表match(或term,见下文)和missing部分使用嵌套属性方法,因为您可以拥有null。数组上的missing只有在缺少整个数组时才匹配,而不是其中的一个值,所以这里不能使用与查询相同的方法,其中值在数组中展平。
  • 是可选的,但对于query match整数,我会使用term,因为它不是字符串而是整数,默认为not_analyzed

如上所述,随着上述变化,这些都是变化:

{
  "mappings" : {
    ...
        "props": {
          "type": "nested",
          "include_in_parent": true,
   ...
  1. 应该(并且确实)返回零结果
  2. GET /nesting-test/_search?pretty=true
    {
      "query": {
        "filtered": {
          "filter": {
            "and": [
              {
                "query": {
                  "query_string": { "query": "props.name:((carlover AND premiumshopper) NOT petlover)" }
                }
              },
              {
                "nested": {
                  "path": "props",
                  "filter": {
                    "or": [ { "query": { "match": { "props.client_id": 1 } } }, { "missing": { "field": "props.client_id" } } ]
                  }
                }
              }
            ]
          }
        }
      }
    }
    
    1. 应该(并且确实)只返回1
    2. GET /nesting-test/_search?pretty=true
      {
        "query": {
          "filtered": {
            "filter": {
              "and": [
                {"query": {"query_string": { "query": "props.name:(carlover NOT petlover)" } } },
                {
                  "nested": {
                    "path": "props",
                    "filter": {
                      "or": [{ "query": { "match": { "props.client_id": 1 } } },{ "missing": { "field": "props.client_id" } } ]
                    }
                  }
                }
              ]
            }
          }
        }
      }
      
      1. 应该(并且确实)只返回2
      2. GET /nesting-test/_search?pretty=true
        {
          "query": {
            "filtered": {
              "filter": {
                "and": [
                  { "query": {"query_string": { "query": "props.name:(* NOT carlover)" } } },
                  {
                    "nested": {
                      "path": "props",
                      "filter": {
                        "or": [{ "query": { "term": { "props.client_id": 1 } } },{ "missing": { "field": "props.client_id" } }
                        ]
                      }
                    }
                  }
                ]
              }
            }
          }
        }