Remove elements/objects From Array in ElasticSearch Followed by Matching Query
Unlike add()
, remove()
takes the index of the element and remove it.
Your ctx._source.locations
in painless is an ArrayList
. It has List
's remove()
method:
E remove(int index)
Removes the element at the specified position in this list (optional operation). ...
See Painless API - List for other methods.
See this answer for example code.
In painless scripts, Array.remove()
method removes by index, not by value.
Here's a working example that removes array elements by value in Elasticsearch script:
POST objects/_update_by_query{ "query": { ... // use regular ES query to remove only in relevant documents }, "script": { "source": """ if (ctx._source[params.array_attribute] != null) { for (int i=ctx._source[params.array_attribute].length-1; i>=0; i--) { if (ctx._source[params.array_attribute][i] == params.value_to_remove) { ctx._source[params.array_attribute].remove(i); } } } """, "params": { "array_attribute": "<NAME_OF_ARRAY_PROPERTY_TO_REMOVE_VALUE_IN>", "value_to_remove": "<VALUE_TO_REMOVE_FROM_ARRAY>", } }}
You might want to simplify script, if your script shall only remove values from one specific array attribute. For example, removing "green"
from document's .color_list
array:
_doc/001 = { "color_list": ["red", "blue", "green"]}
Script to remove "green"
:
POST objects/_update_by_query{ "query": { ... // use regular ES query to remove only in relevant documents }, "script": { "source": """ for (int i=ctx._source.color_list.length-1; i>=0; i--) { if (ctx._source.color_list[i] == params.color_to_remove) { ctx._source.color_list.remove(i); } } """, "params": { "color_to_remove": "green" } }}
"script" : { "lang":"painless", "inline":"ctx._source.locations.remove(params.tag)", "params":{ "tag":indexToRemove }}
If with ctx._source.locations.add(elt)
You add the element, with ctx._source.locations.remove(indexToRemove)
, you remove by the index of element in the array.