Daniel Buckle
Daniel Buckle

Reputation: 628

Elasticsearch - Deleting nested object using java api not working

I have an elasticsearch documents which contain nested objects within them, I want to be able to remove them via the java update api. Here is the code containing the script:

UpdateRequest updateRequest = new UpdateRequest(INDEX, "thread", String.valueOf(threadId));
    updateRequest.script("for (int i = 0; i < ctx._source.messages.size(); i++){if(ctx._source.messages[i]._message_id == " + messageId + ")" +
            "{ctx._source.messages.remove(i);i--;}}", ScriptService.ScriptType.INLINE);
    client.update(updateRequest).actionGet();

This is the mapping of my document:

{
  "thread_and_messages": {
    "mappings": {
      "thread": {
        "properties": {
          "messages": {
            "type": "nested",
            "include_in_parent": true,
            "properties": {
              "message_id": {
                "type": "string"
              },
              "message_nick": {
                "type": "string"
              },
              "message_text": {
                "type": "string"
              }
            }
          },
          "thread_id": {
            "type": "long"
          }
        }
      }
    }
  }
}

I'm not receiving any error messages, but when I run a query on the index to find that nested document it hasn't been removed. Could someone let me know what I am doing wrong?

Upvotes: 1

Views: 933

Answers (1)

Val
Val

Reputation: 217304

Since message_id is a string your script needs to account for it and be modified like this (see the escaped double quotes around the message_id field). There is a second typo, in that your mapping declares a message_id field but you name it _message_id in your script:

"for (int i = 0; i < ctx._source.messages.size(); i++){if(ctx._source.messages[i].message_id == \"" + messageId + "\")"
                                                                                  ^             ^                  ^
                                                                                  |             |                  |
                                                                   no underscore here        add escaped double quotes

Finally also make sure that you have dynamic scripting enabled in your ES config

UPDATE

You can try a "groovy-er" way of removing elements from lists, i.e. no more for loop and if, just use the groovy power:

"ctx._source.messages.removeAll{ it.message_id == \"" + messageId + "\"}"

Normally, that will modify the messages array by removing all elements whose message_id field matches the messageId value.

Upvotes: 2

Related Questions