Update API

edit

Update Request

edit

An UpdateRequest requires the following arguments:

UpdateRequest request = new UpdateRequest(
        "posts", 
        "1");   

Index

Document id

The Update API allows to update an existing document by using a script or by passing a partial document.

Updates with a script

edit

The script can be provided as an inline script:

Map<String, Object> parameters = singletonMap("count", 4); 

Script inline = new Script(ScriptType.INLINE, "painless",
        "ctx._source.field += params.count", parameters);  
request.script(inline);  

Script parameters provided as a Map of objects

Create an inline script using the painless language and the previous parameters

Sets the script to the update request

Or as a stored script:

Script stored = new Script(
        ScriptType.STORED, null, "increment-field", parameters);  
request.script(stored);  

Reference to a script stored under the name increment-field in the painless language

Sets the script in the update request

Updates with a partial document

edit

When using updates with a partial document, the partial document will be merged with the existing document.

The partial document can be provided in different ways:

UpdateRequest request = new UpdateRequest("posts", "1");
String jsonString = "{" +
        "\"updated\":\"2017-01-01\"," +
        "\"reason\":\"daily update\"" +
        "}";
request.doc(jsonString, XContentType.JSON); 

Partial document source provided as a String in JSON format

Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("updated", new Date());
jsonMap.put("reason", "daily update");
UpdateRequest request = new UpdateRequest("posts", "1")
        .doc(jsonMap); 

Partial document source provided as a Map which gets automatically converted to JSON format

XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
    builder.timeField("updated", new Date());
    builder.field("reason", "daily update");
}
builder.endObject();
UpdateRequest request = new UpdateRequest("posts", "1")
        .doc(builder);  

Partial document source provided as an XContentBuilder object, the Elasticsearch built-in helpers to generate JSON content

UpdateRequest request = new UpdateRequest("posts", "1")
        .doc("updated", new Date(),
             "reason", "daily update"); 

Partial document source provided as Object key-pairs, which gets converted to JSON format

Upserts

edit

If the document does not already exist, it is possible to define some content that will be inserted as a new document using the upsert method:

String jsonString = "{\"created\":\"2017-01-01\"}";
request.upsert(jsonString, XContentType.JSON);  

Upsert document source provided as a String

Similarly to the partial document updates, the content of the upsert document can be defined using methods that accept String, Map, XContentBuilder or Object key-pairs.

Optional arguments

edit

The following arguments can optionally be provided:

request.routing("routing"); 

Routing value

request.timeout(TimeValue.timeValueSeconds(1)); 
request.timeout("1s"); 

Timeout to wait for primary shard to become available as a TimeValue

Timeout to wait for primary shard to become available as a String

request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for");                            

Refresh policy as a WriteRequest.RefreshPolicy instance

Refresh policy as a String

request.retryOnConflict(3); 

How many times to retry the update operation if the document to update has been changed by another operation between the get and indexing phases of the update operation

request.fetchSource(true); 

Enable source retrieval, disabled by default

String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(
        new FetchSourceContext(true, includes, excludes)); 

Configure source inclusion for specific fields

String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
request.fetchSource(
        new FetchSourceContext(true, includes, excludes)); 

Configure source exclusion for specific fields

request.setIfSeqNo(2L); 
request.setIfPrimaryTerm(1L); 

ifSeqNo

ifPrimaryTerm

request.detectNoop(false); 

Disable the noop detection

request.scriptedUpsert(true); 

Indicate that the script must run regardless of whether the document exists or not, ie the script takes care of creating the document if it does not already exist.

request.docAsUpsert(true); 

Indicate that the partial document must be used as the upsert document if it does not exist yet.

request.waitForActiveShards(2); 
request.waitForActiveShards(ActiveShardCount.ALL); 

Sets the number of shard copies that must be active before proceeding with the update operation.

Number of shard copies provided as a ActiveShardCount: can be ActiveShardCount.ALL, ActiveShardCount.ONE or ActiveShardCount.DEFAULT (default)

Synchronous execution

edit

When executing a UpdateRequest in the following manner, the client waits for the UpdateResponse to be returned before continuing with code execution:

UpdateResponse updateResponse = client.update(
        request, RequestOptions.DEFAULT);

Synchronous calls may throw an IOException in case of either failing to parse the REST response in the high-level REST client, the request times out or similar cases where there is no response coming back from the server.

In cases where the server returns a 4xx or 5xx error code, the high-level client tries to parse the response body error details instead and then throws a generic ElasticsearchException and adds the original ResponseException as a suppressed exception to it.

Asynchronous execution

edit

Executing a UpdateRequest can also be done in an asynchronous fashion so that the client can return directly. Users need to specify how the response or potential failures will be handled by passing the request and a listener to the asynchronous update method:

client.updateAsync(request, RequestOptions.DEFAULT, listener); 

The UpdateRequest to execute and the ActionListener to use when the execution completes

The asynchronous method does not block and returns immediately. Once it is completed the ActionListener is called back using the onResponse method if the execution successfully completed or using the onFailure method if it failed. Failure scenarios and expected exceptions are the same as in the synchronous execution case.

A typical listener for update looks like:

listener = new ActionListener<UpdateResponse>() {
    @Override
    public void onResponse(UpdateResponse updateResponse) {
        
    }

    @Override
    public void onFailure(Exception e) {
        
    }
};

Called when the execution is successfully completed.

Called when the whole UpdateRequest fails.

Update Response

edit

The returned UpdateResponse allows to retrieve information about the executed operation as follows:

String index = updateResponse.getIndex();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
    
} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
    
} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
    
} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
    
}

Handle the case where the document was created for the first time (upsert)

Handle the case where the document was updated

Handle the case where the document was deleted

Handle the case where the document was not impacted by the update, ie no operation (noop) was executed on the document

When the source retrieval is enabled in the UpdateRequest through the fetchSource method, the response contains the source of the updated document:

GetResult result = updateResponse.getGetResult(); 
if (result.isExists()) {
    String sourceAsString = result.sourceAsString(); 
    Map<String, Object> sourceAsMap = result.sourceAsMap(); 
    byte[] sourceAsBytes = result.source(); 
} else {
    
}

Retrieve the updated document as a GetResult

Retrieve the source of the updated document as a String

Retrieve the source of the updated document as a Map<String, Object>

Retrieve the source of the updated document as a byte[]

Handle the scenario where the source of the document is not present in the response (this is the case by default)

It is also possible to check for shard failures:

ReplicationResponse.ShardInfo shardInfo = updateResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
    
}
if (shardInfo.getFailed() > 0) {
    for (ReplicationResponse.ShardInfo.Failure failure :
            shardInfo.getFailures()) {
        String reason = failure.reason(); 
    }
}

Handle the situation where number of successful shards is less than total shards

Handle the potential failures

When a UpdateRequest is performed against a document that does not exist, the response has 404 status code, an ElasticsearchException gets thrown which needs to be handled as follows:

UpdateRequest request = new UpdateRequest("posts", "does_not_exist")
        .doc("field", "value");
try {
    UpdateResponse updateResponse = client.update(
            request, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
    if (e.status() == RestStatus.NOT_FOUND) {
        
    }
}

Handle the exception thrown because the document not exist

If there is a version conflict, an ElasticsearchException will be thrown:

UpdateRequest request = new UpdateRequest("posts", "1")
        .doc("field", "value")
        .setIfSeqNo(101L)
        .setIfPrimaryTerm(200L);
try {
    UpdateResponse updateResponse = client.update(
            request, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
    if (e.status() == RestStatus.CONFLICT) {
        
    }
}

The raised exception indicates that a version conflict error was returned.