12

I'm having issues trying to remove elements/objects from an array in elasticsearch.

This is the mapping for the index:

{
    "example1": {
        "mappings": {
            "doc": {
                "properties": {
                    "locations": {
                        "type": "geo_point"
                    },
                    "postDate": {
                        "type": "date"
                    },
                    "status": {
                        "type": "long"
                    },
                    "user": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            }
        }
    }
}

And this is an example document.

{
    "_index": "example1",
    "_type": "doc",
    "_id": "8036",
    "_score": 1,
    "_source": {
        "user": "kimchy8036",
        "postDate": "2009-11-15T13:12:00",
        "locations": [
            [
                72.79887719999999,
                21.193036000000003
            ],
            [
                -1.8262150000000001,
                51.178881999999994
            ]
        ]
    }
}

Using the query below, I can add multiple locations.

POST /example1/_update_by_query
{
    "query": {
        "match": {
            "_id": "3"
        }
    },
    "script": {
        "lang": "painless",
        "inline": "ctx._source.locations.add(params.newsupp)",
        "params": {
            "newsupp": [
                -74.00,
                41.12121
            ]
        }
    }
}

But I'm not able to remove array objects from locations. I have tried the query below but it's not working.

POST example1/doc/3/_update
{
    "script": {
        "lang": "painless",
        "inline": "ctx._source.locations.remove(params.tag)",
        "params": {
            "tag": [
                -74.00,
                41.12121
            ]
        }
    }
}

Kindly let me know where i am doing wrong here. I am using elastic version 5.5.2

2
  • 1
    Try using the _update_by_query instead of _update endpoint Commented Mar 20, 2018 at 14:13
  • I also tried _update_by_query. But it also not working. POST /example1/_update_by_query { "query": { "match": { "_id": "3" } }, "script" : { "lang":"painless", "inline": "ctx._source.locations.remove(params.newsupp)", "params":{ "newsupp":[-74.00,41.12121 ] }} } Commented Mar 21, 2018 at 4:47

4 Answers 4

11

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"
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

4

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.

Comments

1
"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.

1 Comment

I was struggling to remove a few records on a pipeline and that saved my day. Thx for your contribution.
1
POST /your_index/_update_by_query
{
  "script": {
    "source": "ctx._source.your_array.removeIf(item -> item == params.value)",
    "lang": "painless",
    "params": {
      "value": "value_to_remove"
    }
  },
  "query": {
    "term": {
      "your_array": "value_to_remove"
    }
  }
}

1 Comment

this is how you can write one line code to remove that element

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.