如何使用过滤器脚本迭代Elasticsearch中的嵌套数组? [英] How to iterate through a nested array in elasticsearch with filter script?

查看:85
本文介绍了如何使用过滤器脚本迭代Elasticsearch中的嵌套数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Elasticsearch中过滤嵌套字段.好吧,我需要根据某些规则退还某些文件.要重现我得到的错误,可以通过以下示例进行指导:

I am trying to filter for a nested field in elasticsearch. Well, I need to return certain documents depending on certain rules. To reproduce the error I'm getting, you can be guided by this example:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "group": "fans",
  "user": [
    {
      "first": "John",
      "last": "Smith"
    },
    {
      "first": "Alice",
      "last": "White"
    }
  ]
}

可以看出,我们有一组对象(嵌套).

As can be seen, we have an array of objects (nested).

我需要在嵌套字段上应用脚本,以便我可以遍历用户数组.

I need to apply a script on the nested field where I can go through the array of users.

例如,我尝试过:

GET my-index-000001/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "filter": [
            {
              "script": {
                "script": {
                  "inline": """
                  def users = doc['user'];
                  for ( int i = 0; i < users.size(); i++ ) {
                    
                  }
                  return true;
                  """
                }
              }
            }
          ]
        }
      }
    }
  }
}

我收到此错误

{
  ...
          "script_stack" : [
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:90)",
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:41)",
            "users = doc['user'];\n                  ",
            "            ^---- HERE"
          ],
          ...
          "caused_by" : {
            "type" : "illegal_argument_exception",
            "reason" : "No field found for [user] in mapping with types []"
          }
        }
      }
    ]
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

Elasticsearch 7.7版

Elasticsearch version 7.7

可以这样做吗?我已经查看了一些答案,但对我来说还不清楚.

推荐答案

嵌套文档功能强大,因为您保留了某些属性连接,但缺点是无法像

Nested documents are powerful because you retain certain attribute connections but there's the downside of not being able to iterate over them as discussed here.

话虽如此,您可以使用

With that being said you could flatten the users attributes using the copy_to feature like so:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "user__first_flattened": {
        "type": "keyword"
      },
      "user": {
        "type": "nested",
        "properties": {
          "first": {
            "type": "keyword",
            "copy_to": "user__first_flattened"
          }
        }
      }
    }
  }
}

然后

PUT my-index-000001/_doc/1
{
  "group": "fans",
  "user": [
    {
      "first": "John",
      "last": "Smith"
    },
    {
      "first": "Alice",
      "last": "White"
    }
  ]
}

现在,您可以访问字段值并可以对其进行迭代(并且可以使用循环索引来帮助找到/识别正确的嵌套"子文档(如果需要).)仅在您进行迭代的前提下可以工作在每个嵌套子文档中表示的字段上,这样就不会缩短循环:

Now you've got access to the field values and can iterate over them (and possibly use the loop index to help locate/identify the correct 'nested' subdocument, if needed.) This only works under the assumption that you iterate over the field that's represented in each nested subdocument so that your loop is not cut short:

GET my-index-000001/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "script": {
            "script": {
              "inline": """
                  def users = doc.user__first_flattened;
                  // users == [Alice, John]
                  for ( int i = 0; i < users.size(); i++ ) {
                    
                  }
                  return true;
                  """
            }
          }
        }
      ]
    }
  }
}

请注意,我们不再在该上下文中进行嵌套查询,因为我们不在该上下文中,并且可以在根目录中使用展平的字段.

Notice that we're not doing a nested query anymore b/c we're outside of that context and got our flattened field available in the root.

值得一提的是,您可以将 copy_to 替换为 include_in_root a>在这里同样有用.

It's also worth knowing that you can replace copy_to with include_in_root which is equally useful here.

这篇关于如何使用过滤器脚本迭代Elasticsearch中的嵌套数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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