loretoparisi
loretoparisi

Reputation: 16309

Update index with script in ElasticSearch Bulk JavaScript API

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

Answers (1)

villasv
villasv

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

Related Questions