【问题标题】:Logstash to add new non existing nested field in all query matching documents?Logstash 在所有查询匹配文档中添加新的不存在的嵌套字段?
【发布时间】:2021-05-30 00:01:50
【问题描述】:

我正在使用 ELK 7.12。
我的外部 json :

{"req-id":"Test9","process-code":"demo9","field1":1,"field2":"abc"}

Elasticsearch 文档:

{"docid":"...", "h":{...},"a":{...}}

预期输出:

{"docid":"...", "h":{...},"a":{...}, "externaldata":{"field1":1,"field2":"abc"}}

Logstash 管道:

filter {
    elasticsearch {
        hosts => "http://localhost:9200/"
        user => elastic
        password => elastic
        index => "demo7"
        query => "h.req-id:%{[req-id]} AND h.process-code:%{[process-code]}"
        docinfo_fields => {
          "_id" => "docid"
        }
    }
    if ("_elasticsearch_lookup_failure" not in [tags]) {
        mutate {
            add_field => {"externaldata"=>{}}
            add_field => { "externaldatafield1" => "%{[field1]}" }
            add_field => { "externaldatafield2" => "%{[field2]}" }
        }
        mutate {
            rename => {
                "externaldatafield1" => "[externaldata][field1]"
                "externaldatafield2" => "[externaldata][field2]"
            }
        }
    }
}
output {
    elasticsearch {
        hosts => "http://localhost:9200/"
        user => elastic
        password => elastic
        index => "demo7"
        action => "update"
        doc_as_upsert => true
        document_id => "%{docid}"
    }
}

错误:

"error"=>{"type"=>"mapper_parsing_exception", "reason"=>"failed to parse field [externaldata] of type [text] in document with id '901'. Preview of field's value: '{field1=1, field2=abcd}'"

我尝试了其他 SO 帖子中的几种组合以在事件中添加嵌套字段,但管道无法执行。请给我正确的语法。我的学习参考是this。

编辑 1:
根据leadrojmp 的评论,GET /demo7/_mapping 的结果是:

"externaldata" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }

在研究了映射概念后,我成功删除了索引并重新执行了管道。

现在的问题是,2 个查询匹配文档中只有一个被更新。 如何使用externaldata 字段更新所有查询匹配文档?如果我应该使用任何循环/跳转代码,请提供参考?

编辑 2:
leandrojmp 解决了我关于附加字段和映射错误的原始问题;因此接受他们的回答。但是多文档更新问题仍然存在。到目前为止,我明白我们应该使用“http”或“exec”插件而不是“elasticsearch”。

【问题讨论】:

    标签: elasticsearch logstash pipeline logstash-configuration


    【解决方案1】:

    此错误意味着您的索引中已经有一个文档,其中字段 externaldata 的类型为 text,而现在您正尝试索引与 object 相同的字段。

    例如,如果在一个文档中您有 externaldata 作为文本:

    { 
        "externaldata": "some string text value" 
    }
    

    在其他文档中,您有 externaldata 和对象:

    { 
        "externaldata": {
            "field1": "1",
            "field2": "2"
        }
    }
    

    这两个文档中的一个将被拒绝,哪个取决于您的映射,如果您没有显式应用映射,elasticsearch 将为其首先收到的类型创建一个映射,在您的情况下似乎成为text 类型。

    要解决此问题,您需要删除索引并为字段mapping 应用externaldata 或索引此字段为对象的文档。

    映射是这样的:

    {
        "externaldata": {
            "properties: {
                "field1": { "type": "keyword" },
                "field2": { "type": "keyword" }
            }
        }   
    } 
    

    如果在您的数据中,该字段不是对象的文档,则需要更改其名称,您不能将相同的字段作为字符串和对象。

    另外,你的 mutate 过滤器是错误的,你只需要这样的东西:

    mutate {
        add_field => { "[externaldata][field1]" => "%{[field1]}" }
        add_field => { "[externaldata][field2]" => "%{[field2]}" }
    }
    

    【讨论】:

    • 您好,感谢您提供所有详细信息。我在任何地方都没有“externaldata”字段 - 在 elasticsearch doc 和外部 json 中都没有。我想在从外部 json 插入 2 个新字段以匹配 ES 文档时创建它。是的,我尝试了你的组合,但得到了同样的错误。
    • 当您尝试索引具有不同映射类型的字段时,将存在映射错误,索引中的字段externaldata被映射为text,为此它被索引为这样之前或应用了显式映射。在 Kibana 开发工具中运行 GET /demo7/_mapping 并使用字段 externaldata 的映射结果更新您的问题。
    • 感谢leadrojmp 关于映射评论,它对我来说是新概念。请检查我的编辑 1 部分并建议我更新所有查询满足文档的方法。我一次又一次地执行相同的管道,但什么也没发生。它总是只更新 1 个文档 :(
    猜你喜欢
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2022-09-24
    相关资源
    最近更新 更多