【问题标题】:How to rename a nested field containing dots with elasticsearch rename processor and ingest pipeline如何使用弹性搜索重命名处理器和摄取管道重命名包含点的嵌套字段
【发布时间】:2018-04-14 01:04:48
【问题描述】:

我在 elasticsearch (5.5.1) 中有一个字段,我需要重命名该字段,因为该名称包含“。”它正在引起各种问题。我要重命名的字段嵌套在另一个字段中。

我正在尝试在摄取管道中使用重命名处理器来执行重新索引,如下所述:https://stackoverflow.com/a/43142634/5114

这是我的管道模拟请求(您可以将其逐字复制到 Kibana 的开发工具实用程序中进行测试):

POST _ingest/pipeline/_simulate
{
    "pipeline" : {
        "description": "rename nested fields to remove dot",
            "processors": [
            {
                "rename" : {
                    "field" : "message.message.group1",
                    "target_field" : "message_group1"
                }
            },
            {
                "rename" : {
                    "field" : "message.message.group2",
                    "target_field" : "message.message_group2"
                }
            }
            ]
    },
    "docs":[
        {
            "_type": "status",
            "_id": "1509533940000-m1-bfd7183bf036bd346a0bcf2540c05a70fbc4d69e",
            "_version": 5,
            "_score": null,
            "_source": {
                "message": {
                    "_job-id": "AV8wHJEaa4J0sFOfcZI5",
                    "message.group1": 0,
                    "message.group2": "foo"
                },
                "timestamp": 1509533940000
            }
        }
    ]
}

问题是我在尝试使用我的管道时遇到错误:

{
  "docs": [
    {
      "error": {
        "root_cause": [
          {
            "type": "exception",
            "reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
            "header": {
              "processor_type": "rename"
            }
          }
        ],
        "type": "exception",
        "reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
        "caused_by": {
          "type": "illegal_argument_exception",
          "reason": "java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "field [message.message.group1] doesn't exist"
          }
        },
        "header": {
          "processor_type": "rename"
        }
      }
    }
  ]
}

我认为问题是由字段“message.group1”在另一个字段(“消息”)内引起的。我不确定如何在处理器的上下文中引用我想要的字段。嵌套字段、包含点的字段和包含点的嵌套字段之间似乎存在歧义。

我正在寻找引用这些字段的正确方法,或者如果 Elasticsearch 无法执行我想要的操作,请确认这是不可能的。如果 Elasticsearch 可以做到这一点,那么它可能会非常快,否则我必须编写一个外部脚本来提取文档、转换它们,然后将它们重新保存到新索引中。

【问题讨论】:

标签: elasticsearch rename pipeline reindex


【解决方案1】:

好的,调查一下 Elasticsearch 代码,我想我知道为什么这行不通了。

首先我们看一下 Elasticsearch 重命名处理器: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/RenameProcessor.java#L76-L84

Object value = document.getFieldValue(field, Object.class);
document.removeField(field);
try {
    document.setFieldValue(targetField, value);
} catch (Exception e) {
    // setting the value back to the original field shouldn't as we just fetched it from that field:
    document.setFieldValue(field, value);
    throw e;
}

这样做是寻找要重命名的字段,获取其值,然后删除该字段并添加一个具有相同值但具有新名称的新字段。

现在我们看看 document.getFieldValue 中发生了什么: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L101-L108

public <T> T getFieldValue(String path, Class<T> clazz) {
    FieldPath fieldPath = new FieldPath(path);
    Object context = fieldPath.initialContext;
    for (String pathElement : fieldPath.pathElements) {
        context = resolve(pathElement, path, context);
    }
    return cast(path, context, clazz);
}

请注意,它使用 FieldPath 对象来表示文档中字段的路径。

现在看看 FieldPath 是如何表示路径的: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L688

this.pathElements = newPath.split("\\.");

这是在任何“。”上分割路径。字符,因为这是字段名称中路径元素之间的分隔符。

问题是源文档有一个名为“message.group1”的字段,所以我们需要能够引用它。只是在“。”上分割路径。不考虑包含“。”的字段名称。在名字里。为此,我们需要一种更像 javascript 的语法,我们可以在其中使用括号和引号来使点表示不同的含义。

如果源文件都被转换成“.”在字段名称中将在保存之前将该字段转换为对象,然后此路径方案将起作用。但是对于具有包含“。”的字段名称的源文档。我们不能在某些情况下引用它们。

为了解决我的问题并重新索引我的索引,我编写了一个 python 脚本,该脚本提取了一批文档,对其进行了转换并将它们批量插入到新索引中。这基本上是 Elasticsearch reindex api 所做的,但我是在 python 中做的。

【讨论】:

    【解决方案2】:

    两年多后,我遇到了同样的问题。您可以使用dot_expander 处理器将您的点属性扩展为真正的嵌套对象。

    将带有点的字段扩展为对象字段。该处理器允许管道中的其他处理器访问名称中带有点的字段。否则任何处理器都无法访问这些字段

    Issue 37507 on Elasticsearch's Github 为我指明了正确的方向。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      • 2016-08-06
      • 1970-01-01
      • 2021-06-08
      • 2020-09-25
      • 2017-10-12
      相关资源
      最近更新 更多