Logstash 在所有查询匹配文档中添加新的不存在的嵌套字段?
Logstash to add new non existing nested field in all query matching documents?
我正在使用 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:
根据 leandrojmp 的评论,GET /demo7/_mapping
的结果是:
"externaldata" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
在学习了映射概念后,我删除了索引并成功地重新执行了管道。
现在的问题是,只更新了 2 个查询匹配文档中的一个。
如何使用 externaldata
字段更新所有查询匹配文档?如果我应该使用任何 loop/jump 代码,请提供参考?
编辑 2:
我原来关于附加字段和映射错误的问题已由leandrojmp解决;因此接受他们的回答。但是多文档更新问题仍然存在。到目前为止,我明白我们应该使用“http”或“exec”插件而不是“elasticsearch”。
此错误意味着您的索引中已有一个文档,其中字段 externaldata
的类型为 text
,现在您正试图将同一字段作为 object
编制索引.
例如,如果您在一个文档中将 externaldata
作为文本:
{
"externaldata": "some string text value"
}
并且在其他文档中您有 externaldata
作为对象:
{
"externaldata": {
"field1": "1",
"field2": "2"
}
}
这两个文档中的一个将被拒绝,哪一个将取决于您的映射,如果您没有明确应用映射,elasticsearch 将为其首先接收到的类型创建一个映射,在您的情况下似乎是 text
类型。
要解决此问题,您需要删除索引并为字段 externaldata
应用 mapping 或索引此字段为对象的文档。
映射应该是这样的:
{
"externaldata": {
"properties: {
"field1": { "type": "keyword" },
"field2": { "type": "keyword" }
}
}
}
如果在您的数据中有文档,其中此字段不是对象,您将需要更改其名称,您不能将相同的字段作为字符串和对象。
另外,你的 mutate 过滤器是错误的,你只需要这样的东西:
mutate {
add_field => { "[externaldata][field1]" => "%{[field1]}" }
add_field => { "[externaldata][field2]" => "%{[field2]}" }
}
我正在使用 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:
根据 leandrojmp 的评论,GET /demo7/_mapping
的结果是:
"externaldata" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
在学习了映射概念后,我删除了索引并成功地重新执行了管道。
现在的问题是,只更新了 2 个查询匹配文档中的一个。
如何使用 externaldata
字段更新所有查询匹配文档?如果我应该使用任何 loop/jump 代码,请提供参考?
编辑 2:
我原来关于附加字段和映射错误的问题已由leandrojmp解决;因此接受他们的回答。但是多文档更新问题仍然存在。到目前为止,我明白我们应该使用“http”或“exec”插件而不是“elasticsearch”。
此错误意味着您的索引中已有一个文档,其中字段 externaldata
的类型为 text
,现在您正试图将同一字段作为 object
编制索引.
例如,如果您在一个文档中将 externaldata
作为文本:
{
"externaldata": "some string text value"
}
并且在其他文档中您有 externaldata
作为对象:
{
"externaldata": {
"field1": "1",
"field2": "2"
}
}
这两个文档中的一个将被拒绝,哪一个将取决于您的映射,如果您没有明确应用映射,elasticsearch 将为其首先接收到的类型创建一个映射,在您的情况下似乎是 text
类型。
要解决此问题,您需要删除索引并为字段 externaldata
应用 mapping 或索引此字段为对象的文档。
映射应该是这样的:
{
"externaldata": {
"properties: {
"field1": { "type": "keyword" },
"field2": { "type": "keyword" }
}
}
}
如果在您的数据中有文档,其中此字段不是对象,您将需要更改其名称,您不能将相同的字段作为字符串和对象。
另外,你的 mutate 过滤器是错误的,你只需要这样的东西:
mutate {
add_field => { "[externaldata][field1]" => "%{[field1]}" }
add_field => { "[externaldata][field2]" => "%{[field2]}" }
}