Reputation: 16309
I'm using ElasticSearch Update action with Upserts to create or update an existing document in the current Index, when doing in the bulk api like this
{
index: myIndex,
type: '_doc',
body: [
{ index: {_id: docItemID1 } },
docItem1,
{ index: {_id: docItemID2 } },
docItem2
]
}
This works ok. Now I would like to update / append a new value to a tag
field in the document item using the scripted_upsert
flag and the script
update action so something like:
{
"scripted_upsert":true,
"script" : {
"source": "if ( !ctx._source.tags.contains(params.tag) ) ctx._source.tag.concat( params.tag)",
"lang": "painless",
"params" : {
"tag" : "blue"
}
},
"upsert" : {
"tag" : ["red","green"]
}
}
Now, I want to use the scripted_upsert
to take the best of the two worlds, so I imagine something like this - if it is correct (that is my question)
{
"script" : {
"source": "if ( !ctx._source.tags.contains(params.tag) ) ctx._source.tag.concat( params.tag)",
"lang": "painless",
"params" : {
"tag" : myNewTag
}
},
"upsert" : docItem
}
where docItem
will contain a tag
item to be updated. This tag items is a comma separated list of tags like red,green
.
Is this approach correct? If so which is the right body for the bulk
api i.e. when using the body
as []
of actions having an update script
with plus scripted_upsert
flag for one or more items?
Upvotes: 2
Views: 6669
Reputation: 6861
That's correct, the docs say:
If you would like your script to run regardless of whether the document exists or not - [...] - then set
scripted_upsert
to true
So having both "upsert" and "script" sections is the way to go, but you have to keep the "scripted_upsert":true
(which is missing from the last snippet).
Using the elasticsearch-js lib, it goes like this:
await client.bulk({
index: 'myIndex',
type: 'myType',
body [
{ update: { _id: docId } },
{ script: { source, params }, scripted_upsert: true, upsert: docItem },
],
});
Upvotes: 3