ES查询以匹配数组中的所有元素 [英] ES query to match all elements in array

查看:3483
本文介绍了ES查询以匹配数组中的所有元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我得到了带有
嵌套数组的文档,该数组要通过此查询进行过滤。

So I got this document with a nested array that I want to filter with this query.

我希望ES返回所有项目更改为0的所有文档仅此而已。
如果文档在列表中甚至只有一个项的更改= 1,则将其丢弃。

I want ES to return all documents where all items have changes = 0 and that only. If document has even a single item in the list with a change = 1, that's discarded.

有什么方法可以从我已经写过的查询开始实现?还是应该使用脚本?

Is there any way I can achieve this starting from the query I have already wrote? Or should I use a script instead?

文档:

{
    "id": "abc",
    "_source" : {
        "trips" : [
            {
                "type" : "home",
                "changes" : 0
            },
            {
                "type" : "home",
                "changes" : 1
            }
        ]
    }
},
{
        "id": "def",
        "_source" : {
            "trips" : [
                {
                    "type" : "home",
                    "changes" : 0
                },
                {
                    "type" : "home",
                    "changes" : 0
                }
            ]
        }
    }

查询:

GET trips_solutions/_search

    {
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "id": {
                  "value": "abc"
                }
              }
            },
            {
              "nested": {
                "path": "trips",
                "query": {
                  "range": {
                    "trips.changes": {
                      "gt": -1,
                      "lt": 1
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }

预期结果:

{
            "id": "def",
            "_source" : {
                "trips" : [
                    {
                        "type" : "home",
                        "changes" : 0
                    },
                    {
                        "type" : "home",
                        "changes" : 0
                    }
                ]
            }
        }

Elasticsearch版本:7.6.2

已经阅读了此答案,但对我没有帮助:
https://discuss.elastic.co/t/how-to-match-all-item -in-nested-array / 163873
ElasticSearch:如何查询精确的嵌套数组

Already read this answers but they didn't help me: https://discuss.elastic.co/t/how-to-match-all-item-in-nested-array/163873 ElasticSearch: How to query exact nested array

推荐答案

首先,如果您通过 id进行过滤: abc ,显然您将无法获得 id:def

First off, if you filter by id: abc, you obviously won't be able to get id: def back.

第二次,由于由于被视为单独的子文档的嵌套字段的性质,您不能查询所有具有<$的行程 c $ c> changes 等于0-各个行程之间的连接丢失,并且

Second, due to the nature of nested fields which are treated as separate subdocuments, you cannot query for all trips that have the changes equal to 0 -- the connection between the individual trips is lost and they "don't know about each other".

可以执行的操作是仅使用返回与嵌套查询匹配的行程inner_hits

What you can do is return only the trips that matched your nested query using inner_hits:

GET trips_solutions/_search
{
  "_source": "false",
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "inner_hits": {},
            "path": "trips",
            "query": {
              "term": {
                "trips.changes": {
                  "value": 0
                }
              }
            }
          }
        }
      ]
    }
  }
}

然后,最简单的解决方案是将嵌套信息动态保存在父对象上喜欢在此处讨论并在结果数组上使用范围/项查询。

The easiest solution then is to dynamically save this nested info on a parent object like discussed here and using range/term query on the resulting array.

编辑:

这是使用方法 copy_to 到文档的最高级别:

Here's how you do it using copy_to onto the doc's top level:

PUT trips_solutions
{
  "mappings": {
    "properties": {
      "trips_changes": {
        "type": "integer"
      },
      "trips": {
        "type": "nested",
        "properties": {
          "changes": {
            "type": "integer",
            "copy_to": "trips_changes"
          }
        }
      }
    }
  }
}

trips_changes 将是一个数字数组-我认为它们是整数,但更多类型可用

trips_changes will be an array of numbers -- I presume they're integers but more types are available.

然后同步一些文档:

POST trips_solutions/_doc
{"trips":[{"type":"home","changes":0},{"type":"home","changes":1}]}

POST trips_solutions/_doc
{"trips":[{"type":"home","changes":0},{"type":"home","changes":0}]}

最后查询:

GET trips_solutions/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "trips",
            "query": {
              "term": {
                "trips.changes": {
                  "value": 0
                }
              }
            }
          }
        },
        {
          "script": {
            "script": {
              "source": "doc.trips_changes.stream().filter(val -> val != 0).count() == 0"
            }
          }
        }
      ]
    }
  }
}

请注意,我们通常首先使用嵌套的词条查询进行过滤,以缩小搜索范围(脚本很慢,因此很有用)。然后,我们检查累积的顶级更改中是否有任何非零的更改,并拒绝那些适用的更改。

Note that we first filter normally using the nested term query to narrow down our search context (scripts are slow so this is useful). We then check if there are any non-zero changes in the accumulated top-level changes and reject those that apply.

这篇关于ES查询以匹配数组中的所有元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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