Elasticsearch: 6.4.2
Logstash: 6.4.2
Goal: Index the data if it hasn't been indexed before, otherwise, if the document does exist, then append an array.
Input data round 1:
{ "item": ["1"] }
Input data round 2:
{ "item": ["2"] }
Desired data in Elasticsearch:
{ "item": ["1","2"] }
The below will index the first time the document is seen or append "item" if it has not. However, it will always append even if the value is in the array. e.g. if the below is ran three times in a row, the output would be { "item": ["1","1","1"] }
POST /test/doc/20/_update?pretty
{
"script": {
"lang": "painless",
"source": "ctx._source.item.add(params.itemNew)",
"params": {"itemNew": "1"}
},
"upsert": {
"item" : ["1"]
}
With the addition of logic, it first checks if the value is in "item" and if it is not, then append it. But before it even does that check, it will index it if it does not exist.
POST /test/doc/30/_update?pretty
{
"script": {
"lang": "painless",
"source": "if(ctx._source.item.contains(params.itemNew)) ctx.op = 'noop'; else (ctx._source.item.add(params.itemNew))",
"params": {"itemNew": "1"}
},
"upsert": {
"item" : ["1"]
}
}
I'm trying to take either of the above examples and convert them to Logstash. The best I have been able to figure out is duplicating my first example where it appends to the item array regardless if the value is already present. The problem is that this just concatenates the strings together. So if the document already exists as item "1" and I update it with item "2" it becomes item "12."
output {
elasticsearch {
hosts => ["http://localhost:9200"]
doc_as_upsert => true
script => 'ctx._source.item += "%{[item]}"'
action => "update"
Update:
This works to append an array (as my first example was showing). It is an append with no logic to determine if the value is already present. i.e. will produce { "item": ["1","1","1"] }
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "test20"
doc_as_upsert => true
script => 'ctx._source.timestamp.add("%{[item]}")'
action => "update"
retry_on_conflict=>3
}