弹性搜索嵌套过滤器是包容性的和排他性的 [英] Elasticsearch Nested Filters being inclusive vs. exclusive

查看:111
本文介绍了弹性搜索嵌套过滤器是包容性的和排他性的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



问题是当我们运行我们的查询,如果一个对象有多个道具,如果其中许多道具之一匹配过滤器,其他人对象被返回,当我们想要相反的时候 - 如果一个返回false,那么返回不会返回,如果返回true。



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



提前感谢

解决方案

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



使用嵌套过滤器,您需要将该字符串与道具的所有值相匹配。一个父文档的 c 含义全部嵌套 props.name 需要匹配。那么嵌套对象不会发生这种情况,因为嵌套的文档是分开的并且被单独查询。而且,如果至少有一个嵌套文档匹配,那么它被认为是一个匹配。



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



我的建议是让您的嵌套文档include_in_parent :true (意思是保持在一个扁平化的数组列表中)并更改一些查询:



    $ b $对于 query_string 部分的b
  • ,使用展平属性方法能够将元素的组合列表的查询匹配,而不是逐个元素。

  • 匹配(或术语,见下文)和缺少零件使用嵌套属性方法,因为您可以在其中有 null s。数组中的缺少只有当整个数组丢失时才匹配,而不是其中的一个值,所以这里不能使用与查询相同的方法,其中值
  • 可选,但对于查询 匹配整数我将使用术语,因为它不是字符串,而是整数,默认情况下 not_analyzed



正如上所述,这些更改是这些更改:

 code> {
mappings:{
...
props:{
type:nested,
include_in_parent :true,
...




  1. 应该)返回零结果





  GET / nesting-test / _search?pretty = true 
{
查询:{
过滤:{
过滤器:{
和:[
{
query:{
qu red_string:{query:props.name:((clover and premiumshopper)NOT petlover)}
}
},
{
嵌套:{
path:props,
filter:{
or:[{query:{match:{props.client_id:1}}} ,{missing:{field:props.client_id}}]
}
}
}
]
}
}
}
}




    <应该(并且)只返回1





  GET /嵌套测试/ _search?pretty = true 
{
查询:{
filters:{
filter:{
and
{query:{query_string:{query:props.name:(carlover NOT petlover)}}},
{
嵌套:{
path:props,
filter:{
或:[{query:{matc h:{props.client_id:1}}},{missing:{field:props.client_id}}]
}
}
}
]
}
}
}
}



< ol start =3>

  • 应该(而且)只返回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}}
    ]
    }
    }
    }
    ]
    }
    }
    }
    }


    I have an object mapping that uses nested objects (props in our example) in a tag-like fashion. Each tag can belong to a client/user and when we want to allow our users to generate query_string style searches against the props.name.

    Issue is that when we run our query if an object has multiple props and if one of the many props match the filter when others don't the object is returned, when we want the opposite - if one returns false don't return vs. if one returns true return.

    I have posted a comprehensive example here: https://gist.github.com/d2kagw/1c9d4ef486b7a2450d95

    Thanks in advance.

    解决方案

    I believe here you might need the advantage of a flattened list of values, like an array of values. The major difference between an array and nested objects is that the latter "knows" which value of a nested property corresponds to another value of another property in the same nested object. The array of values, on the other hand will flatten the values of a certain property and you lose the "association" between a client_id and a name. Meaning, with arrays you have props.client_id = [null, 2] and props.name = ["petlover", "premiumshopper"].

    With your nested filter you want to match that string to all values for props.name meaning ALL nested props.names of one parent doc needs to match. Well, this doesn't happen with nested objects, because the nested documents are separate and are queried separately. And, if at least one nested document matches then it's considered a match.

    In other words, for a query like "query": "props.name:(carlover NOT petlover)" you basically need to run it against a flattened list of values, just like arrays. You need that query ran against ["carlover", "petlover"].

    My suggestion for you is to make your nested documents "include_in_parent": true (meaning, keep in parent a flattened, array-like list of values) and change a bit the queries:

    • for the query_string part, use the flattened properties approach to be able to match your query for a combined list of elements, not element by element.
    • for the match (or term, see below) and missing parts use the nested properties approach because you can have nulls in there. A missing on an array will match only if the whole array is missing, not one value in it, so here one cannot use the same approach as for the query, where the values were flattened in an array.
    • optional, but for the query match integer I would use term, as it's not string but integer and is by default not_analyzed.

    These being said, with the above changes, these are the changes:

    {
      "mappings" : {
        ...
            "props": {
              "type": "nested",
              "include_in_parent": true,
       ...
    

    1. should (and does) return zero results

    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. should (and does) return just 1

    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. should (and does) return just 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" } }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
    

    这篇关于弹性搜索嵌套过滤器是包容性的和排他性的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆