Add elements in nested object with JAVA API 5.6 and painless

Hi everyone, I’m trying to add elements on a nested array on an existing document using painless script .

I’m using :

  • elastic search server 5.6.9
  • org.elasticsearch.client:elasticsearch:5.6.9
  • org.elasticsearch.client:transport:5.6.9

I tried on Kibana the following request and it works.

POST user_transaction_1/transaction/100000/_update
{
  "script": {
    "lang": "painless",
    "source": "ctx._source.transactions.addAll(params.newTransactions)",
    "params": {
        "newTransactions": [
          {"accountId":1,"amount":-49.9,"date": 15124284000}
        ]
    }
  }
}

But now I want to do this request using the Java API, I create the following script :

Script updateScript = new Script(Script.DEFAULT_SCRIPT_TYPE,
        "painless",
        "ctx._source.transactions.add(params.newTransaction)",
        ImmutableMap.of("newTransaction", JSON));

UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(index, "transaction", key)
.setScript(updateScript)

If JSON var is a String (JSON of my transaction array) I've got :

ScriptException[runtime error]; nested: NotSerializableExceptionWrapper[class_cast_exception: Cannot cast java.lang.String to java.util.Collection];
at org.elasticsearch.action.update.UpdateHelper.executeScript(UpdateHelper.java:266)

If JSON var is List<String> (Array of json element) I've got :

MapperParsingException[object mapping for [transactions] tried to parse field [null] as object, but found a concrete value]

If JSON var is List<Transaction> (Array of POJO ) I've got :

java.io.IOException: can not write type [class com...Transaction] at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:655) at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrNested(DocumentParser.java:350)

Someone knows how to do this request using JAVA API ??

If JSON var is a String (JSON of my transaction array)

This doesn't work because you are calling addAll with a String, which takes a Collection. If you pass your data as a string, you need to parse it into a collection. Unfortunately painless does not have any built in json parsing.

If JSON var is List (Array of json element)

I think this fails because the transactions object now has mixed data (list and map) which fails somewhere when trying to apply the update.

If JSON var is List (Array of POJO )

This fails because Ealsticsearch does not know how to read/write your Transaction class.

I think the most important thing to notice is from your second example:

[object mapping for [transactions] tried to parse field [null]

When you are trying to update the field, it already this transactions is an object field. You need to set the mapping for this field at index creation to type nested.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.