elastic / elasticsearch-java

Official Elasticsearch Java Client
Apache License 2.0
408 stars 237 forks source link

UpdateOperation didn't serialize the script into the request body. #779

Open syhily opened 4 months ago

syhily commented 4 months ago

Java API client version

8.13.2

Java version

17

Elasticsearch Version

8.11.3

Problem description

I use some code like below to a script execution request in the bulk update operation.

    var builder = new BulkRequest.Builder().index(index);
    for (T t : list) {
        final var uo = new UpdateOperation.Builder<Map<String, String>, T>().index(index).retryOnConflict(3);
        final var id = documentId.documentId(t);
        if (id != null) {
            uo.id(id);
        }

        // Using script
        final var ac = UpdateAction.<Map<String, String>, T>of(a -> a.scriptedUpsert(true)
                .upsert(emptyMap())
                .script(Script.of(s -> s.stored(ss -> ss.id(scriptId)
                        .params("version", JsonData.of(System.currentTimeMillis()))
                        .params("data", JsonData.of(t))))));
        UpdateOperation<Map<String, String>, T> up = uo.action(ac).build();
        builder.operations(new BulkOperation.Builder().update(up).build());
    }

    BulkRequest request = builder.build();

The action part didn't get serialized into the final request body.

l-trotta commented 4 months ago

Hello, thanks for reporting this! Yes it seems like the serializer is ignoring the action field, we'll investigate this.

os-cas commented 3 months ago

Ran into something similar where it strongly depends on how I set the action of the UpdateOperation in a BulkRequest.

I have a pre-serialized JSON which I set like this:

BinaryData binaryData = BinaryData.of(jsonBytes, contentType);
UpdateOperation.of(uo -> uo.index(index).id(id)
     .action(UpdateAction.of(ua -> ua.doc(binaryData)));

but the resulting section in the request body just looks like: {"doc":{"repeatable":true}}

If I first deserialize my JSON into a Map to get rid of the BinaryData it works:

HashMap<String, Object> map = // deserialize JSON...
UpdateOperation.of(uo -> uo.index(index).id(id)
     .action(UpdateAction.of(ua -> ua.doc(map))));

resulting in: {"doc":{"my_field": "some value"}}