Multi-Get API

edit

The multiGet API executes multiple get requests in a single http request in parallel.

Multi-Get Request

edit

A MultiGetRequest is built empty and you add `MultiGetRequest.Item`s to configure what to fetch:

MultiGetRequest request = new MultiGetRequest();
request.add(new MultiGetRequest.Item(
    "index",         
    "type",          
    "example_id"));  
request.add(new MultiGetRequest.Item("index", "type", "another_id"));  

Index

Type

Document id

Add another item to fetch

Optional arguments

edit

multiGet supports the same optional arguments that the get API supports. You can set most of these on the Item:

request.add(new MultiGetRequest.Item("index", "type", "example_id")
    .fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE));  

Disable source retrieval, enabled by default

String[] includes = new String[] {"foo", "*r"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext =
        new FetchSourceContext(true, includes, excludes);
request.add(new MultiGetRequest.Item("index", "type", "example_id")
    .fetchSourceContext(fetchSourceContext));  

Configure source inclusion for specific fields

String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[] {"foo", "*r"};
FetchSourceContext fetchSourceContext =
        new FetchSourceContext(true, includes, excludes);
request.add(new MultiGetRequest.Item("index", "type", "example_id")
    .fetchSourceContext(fetchSourceContext));  

Configure source exclusion for specific fields

request.add(new MultiGetRequest.Item("index", "type", "example_id")
    .storedFields("foo"));  
MultiGetResponse response = client.multiGet(request);
MultiGetItemResponse item = response.getResponses()[0];
String value = item.getResponse().getField("foo").getValue(); 

Configure retrieval for specific stored fields (requires fields to be stored separately in the mappings)

Retrieve the foo stored field (requires the field to be stored separately in the mappings)

request.add(new MultiGetRequest.Item("index", "type", "with_routing")
    .routing("some_routing"));          
request.add(new MultiGetRequest.Item("index", "type", "with_parent")
    .parent("some_parent"));            
request.add(new MultiGetRequest.Item("index", "type", "with_version")
    .versionType(VersionType.EXTERNAL)  
    .version(10123L));                  

Routing value

Parent value

Version

Version type

preference, realtime and refresh can be set on the main request but not on any items:

request.preference("some_preference");  
request.realtime(false);                
request.refresh(true);                  

Preference value

Set realtime flag to false (true by default)

Perform a refresh before retrieving the document (false by default)

Synchronous Execution

edit

After building the MultiGetRequest you can execute it synchronously with multiGet:

MultiGetResponse response = client.multiGet(request);

Asynchronous Execution

edit

The asynchronous execution of a multi get request requires both the MultiGetRequest instance and an ActionListener instance to be passed to the asynchronous method:

client.multiGetAsync(request, listener); 

The MultiGetRequest to execute and the ActionListener to use when the execution completes.

The asynchronous method does not block and returns immediately. Once the request completed the ActionListener is called back using the onResponse method if the execution successfully completed or using the onFailure method if it failed.

A typical listener for MultiGetResponse looks like:

ActionListener<MultiGetResponse> listener = new ActionListener<MultiGetResponse>() {
    @Override
    public void onResponse(MultiGetResponse response) {
        
    }

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

Called when the execution is successfully completed. The response is provided as an argument.

Called in case of failure. The raised exception is provided as an argument.

Multi Get Response

edit

The returned MultiGetResponse contains a list of MultiGetItemResponse`s in `getResponses in the same order that they were requested. MultiGetItemResponse contains either a GetResponse if the get succeeded or a MultiGetResponse.Failure if it failed. A success looks just like a normal GetResponse.

MultiGetItemResponse firstItem = response.getResponses()[0];
assertNull(firstItem.getFailure());              
GetResponse firstGet = firstItem.getResponse();  
String index = firstItem.getIndex();
String type = firstItem.getType();
String id = firstItem.getId();
if (firstGet.isExists()) {
    long version = firstGet.getVersion();
    String sourceAsString = firstGet.getSourceAsString();        
    Map<String, Object> sourceAsMap = firstGet.getSourceAsMap(); 
    byte[] sourceAsBytes = firstGet.getSourceAsBytes();          
} else {
    
}

getFailure returns null because there isn’t a failure.

getResponse returns the GetResponse.

Retrieve the document as a String

Retrieve the document as a Map<String, Object>

Retrieve the document as a byte[]

Handle the scenario where the document was not found. Note that although the returned response has 404 status code, a valid GetResponse is returned rather than an exception thrown. Such response does not hold any source document and its isExists method returns false.

When one of the subrequests as performed against an index that does not exist getFailure will contain an exception:

assertNull(missingIndexItem.getResponse());                
Exception e = missingIndexItem.getFailure().getFailure();  
ElasticsearchException ee = (ElasticsearchException) e;    
// TODO status is broken! fix in a followup
// assertEquals(RestStatus.NOT_FOUND, ee.status());        
assertThat(e.getMessage(),
    containsString("reason=no such index"));               

getResponse is null.

getFailure isn’t and contains an Exception.

That Exception is actually an ElasticsearchException

and it has a status of NOT_FOUND. It’d have been an HTTP 404 if this wasn’t a multi get.

getMessage explains the actual cause, no such index.

In case a specific document version has been requested, and the existing document has a different version number, a version conflict is raised:

MultiGetRequest request = new MultiGetRequest();
request.add(new MultiGetRequest.Item("index", "type", "example_id")
    .version(1000L));
MultiGetResponse response = client.multiGet(request);
MultiGetItemResponse item = response.getResponses()[0];
assertNull(item.getResponse());                          
Exception e = item.getFailure().getFailure();            
ElasticsearchException ee = (ElasticsearchException) e;  
// TODO status is broken! fix in a followup
// assertEquals(RestStatus.CONFLICT, ee.status());          
assertThat(e.getMessage(),
    containsString("version conflict, current version [1] is "
        + "different than the one provided [1000]"));    

getResponse is null.

getFailure isn’t and contains an Exception.

That Exception is actuall and ElasticsearchException

and it has a status of CONFLICT. It’d have been an HTTP 409 if this wasn’t a multi get.

getMessage explains the actual cause, `