From 8826611c5c15797e7226600f0c9749e844efa6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 11 Jul 2017 12:53:35 +0200 Subject: [PATCH 1/2] Starting search request documentation for high level client Initial documentation of high level rest client search request and response. This mostly covers regular search requests and responses and doesn't include aggregations, suggestions and highlighting just yet. --- .../documentation/SearchDocumentationIT.java | 108 ++++++++++++++++++ .../org/elasticsearch/search/SearchHit.java | 2 +- .../java-rest/high-level/apis/search.asciidoc | 101 +++++++++++++++- 3 files changed, 209 insertions(+), 2 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java index 0be7124ec9faa..6f5699d4096d2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java @@ -28,20 +28,27 @@ import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchScrollRequest; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.client.ESRestHighLevelClientTestCase; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.Scroll; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.sort.ScoreSortBuilder; +import org.elasticsearch.search.sort.SortOrder; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.hamcrest.Matchers.greaterThan; @@ -63,6 +70,107 @@ */ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase { + @SuppressWarnings({ "unused", "unchecked" }) + public void testSearch() throws IOException { + RestHighLevelClient client = highLevelClient(); + { + BulkRequest request = new BulkRequest(); + request.add(new IndexRequest("posts", "doc", "1") + .source(XContentType.JSON, "title", "In which order are my Elasticsearch queries executed?", "user", + Arrays.asList("kimchy", "luca"), "innerObject", Collections.singletonMap("key", "value"))); + request.add(new IndexRequest("posts", "doc", "2") + .source(XContentType.JSON, "title", "Current status and upcoming changes in Elasticsearch", "user", + Arrays.asList("kimchy", "christoph"), "innerObject", Collections.singletonMap("key", "value"))); + request.add(new IndexRequest("posts", "doc", "3") + .source(XContentType.JSON, "title", "The Future of Federated Search in Elasticsearch", "user", + Arrays.asList("kimchy", "tanguy"), "innerObject", Collections.singletonMap("key", "value"))); + request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); + BulkResponse bulkResponse = client.bulk(request); + assertSame(bulkResponse.status(), RestStatus.OK); + assertFalse(bulkResponse.hasFailures()); + } + { + // tag::search-request-basic + SearchRequest searchRequest = new SearchRequest(); // <1> + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); // <2> + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // <3> + // end::search-request-basic + + // tag::search-response-basic + SearchResponse searchResponse = client.search(searchRequest); // <1> + TimeValue took = searchResponse.getTook(); + boolean timedOut = searchResponse.isTimedOut(); + SearchHits hits = searchResponse.getHits(); // <2> + long totalHits = hits.getTotalHits(); + double maxScore = hits.getMaxScore(); + SearchHit[] searchHits = hits.getHits(); // <3> + String docId = searchHits[0].getId(); + String documentSource = searchHits[0].getSourceAsString(); + // end::search-response-basic + } + { + // tag::search-request-details + SearchRequest searchRequest = new SearchRequest("posts"); // <1> + searchRequest.types("doc"); // <2> + searchRequest.routing("routing"); // <3> + searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); // <4> + searchRequest.preference("_local"); // <5> + // end::search-request-details + assertNotNull(client.search(searchRequest)); + } + { + // tag::search-source-basics + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // <1> + sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); // <2> + sourceBuilder.from(0); // <3> + sourceBuilder.size(5); // <4> + sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.ASC)); + sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // <5> + + SearchRequest searchRequest = new SearchRequest(); + searchRequest.source(sourceBuilder); + // end::search-source-basics + + // tag::search-response-details + SearchResponse searchResponse = client.search(searchRequest); + RestStatus status = searchResponse.status(); // <1> + TimeValue took = searchResponse.getTook(); // <2> + Boolean terminatedEarly = searchResponse.isTerminatedEarly(); + boolean timedOut = searchResponse.isTimedOut(); + int totalShards = searchResponse.getTotalShards(); // <3> + int successfulShards = searchResponse.getSuccessfulShards(); + int failedShards = searchResponse.getFailedShards(); + if (searchResponse.getShardFailures().length > 0) { + // <4> + } + // end::search-response-details + assertNotNull(searchResponse); + + // tag::search-hits-details + SearchHits hits = searchResponse.getHits(); // <1> + long totalHits = hits.getTotalHits(); // <2> + float maxScore = hits.getMaxScore(); + SearchHit[] searchHits = hits.getHits(); + for (SearchHit hit : searchHits) { // <3> + String index = hit.getIndex(); // <4> + String type = hit.getType(); + String id = hit.getId(); + float score = hit.getScore(); + String sourceAsString = hit.getSourceAsString(); // <5> + Map sourceAsMap = hit.getSourceAsMap(); // <6> + String documentTitle = (String) sourceAsMap.get("title"); // <7> + List users = (List) sourceAsMap.get("user"); // <8> + Map innerObject = (Map) sourceAsMap.get("innerObject"); // <9> + } + // end::search-hits-details + assertEquals(3, totalHits); + assertNotNull(hits.getHits()[0].getSourceAsString()); + assertNotNull(hits.getHits()[0].getSourceAsMap().get("title")); + assertNotNull(hits.getHits()[0].getSourceAsMap().get("user")); + assertNotNull(hits.getHits()[0].getSourceAsMap().get("innerObject")); + } + } + public void testScroll() throws IOException { RestHighLevelClient client = highLevelClient(); { diff --git a/core/src/main/java/org/elasticsearch/search/SearchHit.java b/core/src/main/java/org/elasticsearch/search/SearchHit.java index db7a6cf8fdb8b..45510ea1af943 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchHit.java +++ b/core/src/main/java/org/elasticsearch/search/SearchHit.java @@ -192,7 +192,7 @@ public NestedIdentity getNestedIdentity() { } /** - * Returns bytes reference, also un compress the source if needed. + * Returns bytes reference, also uncompress the source if needed. */ public BytesReference getSourceRef() { if (this.source == null) { diff --git a/docs/java-rest/high-level/apis/search.asciidoc b/docs/java-rest/high-level/apis/search.asciidoc index 13215806f9bbb..3188d0ae3c2c5 100644 --- a/docs/java-rest/high-level/apis/search.asciidoc +++ b/docs/java-rest/high-level/apis/search.asciidoc @@ -1,4 +1,103 @@ [[java-rest-high-search]] === Search API -To be documented. +[[java-rest-high-document-search-request]] +==== Search Request + +The `SearchRequest` is used for any operation that has to do with retrieving +documents, aggregations, suggestions and also offers ways of requesting +highlighting on the resulting documents. + +In its most basic form, a query can be added to the request like this: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-basic] +-------------------------------------------------- + +<1> Creates the `SeachRequest`. Without arguments this runs against all indices. +<2> Most details about the search can be added to the `SearchSourceBuilder`. +<3> Add a `match_all` query to the `SearchSourceBuilder`. + +When the search is executed, it returns a `SearchResponse` object that serves +as an entry point to a lot of information about the search response and the +results: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-basic] +-------------------------------------------------- + +<1> Actually perform the search. The response contains information about the +execution of the request itself, like the `took` time or if the request timed +out. +<2> Get the `SearchHits` from the response. This object provides access to +global result parameters like number of total hits or the maximum score. +<3> Get the individual `SearchHit` objects. These are returned in the order +determined by the search. `SearchHit` provides access to document details like +its id or the document `source`. + +==== Optional request arguments + +Lets first look at some of the optional argument of a `SearchRequest`. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-details] +-------------------------------------------------- + +<1> The request can be restricted to one or more indices by passing their names +to the constructor. +<2> The request can also be limited to one or more types. +<3> Optional: provide a routing parameter for the request. +<4> Optional: `IndicesOptions` control how unavailable indices are resolved and +how wildcard expressions are expanded +<5> Optional: Set the preference to execute the search to prefer local shards. +Defaults to randomize across shards. + +==== Using the SearchSourceBuilder + +Most options controlling the search behavior can be set on the `SearchSourceBuilder`, +which contains more or less the equivalent of the options in the search request body of the Rest API. + +Here are a few examples of some common options: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-source-basics] +-------------------------------------------------- +<1> Create a `SearchSourceBuilder` with default options. +<2> Set the query. Can be any type of `QueryBuilder` +<3> Set the `from` option that determines the result index to start searching from. Defaults to 0. +<4> Set the `size` option that determines the number of search hits to return. Defaults to 10. +<5> Set an optional timeout that controls how long the search is allowed to take. + +==== Accessing SearchResponse details + +The `SearchResponse` that is returned by performing `client.search(searchRequest)` provides details about the search execution as well as access to the document returned as a result. First, lets look at some of the information provided by the `SearchResponse` itself: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-details] +-------------------------------------------------- +<1> The HTTP status code +<2> Information about query execution time, early termination or timeouts +<3> Information about successful and failed shards for this search +<4> Possible failures could be handled here + +To get access to the returned documents, we need to first get the `SearchHits` contained in the response after which we +can iterate over the individual documents and can access their score and the document source: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-details] +-------------------------------------------------- +<1> Get the `SearchHits` +<2> Get some global information about all hits, like total number of hits or the maximum score +<3> Iterate over the result documents +<4> Access basic information like index, type, docId and score of each search hit +<5> Access document source as a JSON string +<6> Alternatively, access document source as key/value map. +<7> Get regular field from sourceMap using the fields name. +<8> Multi-valued fields are returned as lists of objects and need to be cast accordingly +<9> Nested objects are returned as another key/value map and need to be cast accordingly From 3601df20749725e36917bc5110c65833543b2e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Wed, 12 Jul 2017 10:58:43 +0200 Subject: [PATCH 2/2] Addressing review comments --- .../documentation/SearchDocumentationIT.java | 104 ++++++---- .../java-rest/high-level/apis/search.asciidoc | 183 +++++++++++++----- 2 files changed, 196 insertions(+), 91 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java index 6f5699d4096d2..8d94c68e6291f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java @@ -28,6 +28,7 @@ import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchScrollRequest; +import org.elasticsearch.action.search.ShardSearchFailure; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.client.ESRestHighLevelClientTestCase; @@ -95,27 +96,21 @@ public void testSearch() throws IOException { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); // <2> searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // <3> // end::search-request-basic - - // tag::search-response-basic - SearchResponse searchResponse = client.search(searchRequest); // <1> - TimeValue took = searchResponse.getTook(); - boolean timedOut = searchResponse.isTimedOut(); - SearchHits hits = searchResponse.getHits(); // <2> - long totalHits = hits.getTotalHits(); - double maxScore = hits.getMaxScore(); - SearchHit[] searchHits = hits.getHits(); // <3> - String docId = searchHits[0].getId(); - String documentSource = searchHits[0].getSourceAsString(); - // end::search-response-basic } { - // tag::search-request-details - SearchRequest searchRequest = new SearchRequest("posts"); // <1> - searchRequest.types("doc"); // <2> - searchRequest.routing("routing"); // <3> - searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); // <4> - searchRequest.preference("_local"); // <5> - // end::search-request-details + // tag::search-request-indices-types + SearchRequest searchRequest = new SearchRequest("posts"); + searchRequest.types("doc"); + // end::search-request-indices-types + // tag::search-request-routing + searchRequest.routing("routing"); // <1> + // end::search-request-routing + // tag::search-request-indicesOptions + searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); // <1> + // end::search-request-indicesOptions + // tag::search-request-preference + searchRequest.preference("_local"); // <1> + // end::search-request-preference assertNotNull(client.search(searchRequest)); } { @@ -126,43 +121,76 @@ public void testSearch() throws IOException { sourceBuilder.size(5); // <4> sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.ASC)); sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // <5> + // end::search-source-basics + // tag::search-source-setter SearchRequest searchRequest = new SearchRequest(); searchRequest.source(sourceBuilder); - // end::search-source-basics + // end::search-source-setter - // tag::search-response-details + // tag::search-execute SearchResponse searchResponse = client.search(searchRequest); - RestStatus status = searchResponse.status(); // <1> - TimeValue took = searchResponse.getTook(); // <2> + // end::search-execute + + // tag::search-execute-async + client.searchAsync(searchRequest, new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }); + // end::search-execute-async + + // tag::search-response-1 + RestStatus status = searchResponse.status(); + TimeValue took = searchResponse.getTook(); Boolean terminatedEarly = searchResponse.isTerminatedEarly(); boolean timedOut = searchResponse.isTimedOut(); - int totalShards = searchResponse.getTotalShards(); // <3> + // end::search-response-1 + + // tag::search-response-2 + int totalShards = searchResponse.getTotalShards(); int successfulShards = searchResponse.getSuccessfulShards(); int failedShards = searchResponse.getFailedShards(); - if (searchResponse.getShardFailures().length > 0) { - // <4> + for (ShardSearchFailure failure : searchResponse.getShardFailures()) { + // failures should be handled here } - // end::search-response-details + // end::search-response-2 assertNotNull(searchResponse); - // tag::search-hits-details - SearchHits hits = searchResponse.getHits(); // <1> - long totalHits = hits.getTotalHits(); // <2> + // tag::search-hits-get + SearchHits hits = searchResponse.getHits(); + // end::search-hits-get + // tag::search-hits-info + long totalHits = hits.getTotalHits(); float maxScore = hits.getMaxScore(); + // end::search-hits-info + // tag::search-hits-singleHit SearchHit[] searchHits = hits.getHits(); - for (SearchHit hit : searchHits) { // <3> - String index = hit.getIndex(); // <4> + for (SearchHit hit : searchHits) { + // do something with the SearchHit + } + // end::search-hits-singleHit + for (SearchHit hit : searchHits) { + // tag::search-hits-singleHit-properties + String index = hit.getIndex(); String type = hit.getType(); String id = hit.getId(); float score = hit.getScore(); - String sourceAsString = hit.getSourceAsString(); // <5> - Map sourceAsMap = hit.getSourceAsMap(); // <6> - String documentTitle = (String) sourceAsMap.get("title"); // <7> - List users = (List) sourceAsMap.get("user"); // <8> - Map innerObject = (Map) sourceAsMap.get("innerObject"); // <9> + // end::search-hits-singleHit-properties + // tag::search-hits-singleHit-source + String sourceAsString = hit.getSourceAsString(); + Map sourceAsMap = hit.getSourceAsMap(); + String documentTitle = (String) sourceAsMap.get("title"); + List users = (List) sourceAsMap.get("user"); + Map innerObject = (Map) sourceAsMap.get("innerObject"); + // end::search-hits-singleHit-source } - // end::search-hits-details assertEquals(3, totalHits); assertNotNull(hits.getHits()[0].getSourceAsString()); assertNotNull(hits.getHits()[0].getSourceAsMap().get("title")); diff --git a/docs/java-rest/high-level/apis/search.asciidoc b/docs/java-rest/high-level/apis/search.asciidoc index 3188d0ae3c2c5..52defa6a11f6d 100644 --- a/docs/java-rest/high-level/apis/search.asciidoc +++ b/docs/java-rest/high-level/apis/search.asciidoc @@ -4,11 +4,11 @@ [[java-rest-high-document-search-request]] ==== Search Request -The `SearchRequest` is used for any operation that has to do with retrieving -documents, aggregations, suggestions and also offers ways of requesting +The `SearchRequest` is used for any operation that has to do with searching +documents, aggregations, suggestions and also offers ways of requesting highlighting on the resulting documents. -In its most basic form, a query can be added to the request like this: +In its most basic form, a query can be added to the request like this: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- @@ -16,49 +16,50 @@ include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-basic] -------------------------------------------------- <1> Creates the `SeachRequest`. Without arguments this runs against all indices. -<2> Most details about the search can be added to the `SearchSourceBuilder`. +<2> Most parameters of the search can be added to the `SearchSourceBuilder` +which contains everything that +in the Rest API would be placed in the search request body. <3> Add a `match_all` query to the `SearchSourceBuilder`. -When the search is executed, it returns a `SearchResponse` object that serves -as an entry point to a lot of information about the search response and the -results: +==== Optional arguments + +Lets first look at some of the optional argument of a `SearchRequest`. +First of all, the request can be restricted to one or more indices using the +constructor or to on or more types using a setter: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-basic] +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-indices-types] -------------------------------------------------- -<1> Actually perform the search. The response contains information about the -execution of the request itself, like the `took` time or if the request timed -out. -<2> Get the `SearchHits` from the response. This object provides access to -global result parameters like number of total hits or the maximum score. -<3> Get the individual `SearchHit` objects. These are returned in the order -determined by the search. `SearchHit` provides access to document details like -its id or the document `source`. - -==== Optional request arguments - -Lets first look at some of the optional argument of a `SearchRequest`. +There are a couple of other interesting optional parameters: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-details] +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-routing] -------------------------------------------------- +<1> Set a routing parameter -<1> The request can be restricted to one or more indices by passing their names -to the constructor. -<2> The request can also be limited to one or more types. -<3> Optional: provide a routing parameter for the request. -<4> Optional: `IndicesOptions` control how unavailable indices are resolved and +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-indicesOptions] +-------------------------------------------------- +<1> Setting `IndicesOptions` controls how unavailable indices are resolved and how wildcard expressions are expanded -<5> Optional: Set the preference to execute the search to prefer local shards. -Defaults to randomize across shards. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-preference] +-------------------------------------------------- +<1> Use the preference parameter e.g. to execute the search to prefer local +shards. The The default is to randomize across shards. ==== Using the SearchSourceBuilder -Most options controlling the search behavior can be set on the `SearchSourceBuilder`, -which contains more or less the equivalent of the options in the search request body of the Rest API. +Most options controlling the search behavior can be set on the +`SearchSourceBuilder`, +which contains more or less the equivalent of the options in the search request +body of the Rest API. Here are a few examples of some common options: @@ -66,38 +67,114 @@ Here are a few examples of some common options: -------------------------------------------------- include-tagged::{doc-tests}/SearchDocumentationIT.java[search-source-basics] -------------------------------------------------- -<1> Create a `SearchSourceBuilder` with default options. +<1> Create a `SearchSourceBuilder` with default options. <2> Set the query. Can be any type of `QueryBuilder` -<3> Set the `from` option that determines the result index to start searching from. Defaults to 0. -<4> Set the `size` option that determines the number of search hits to return. Defaults to 10. -<5> Set an optional timeout that controls how long the search is allowed to take. +<3> Set the `from` option that determines the result index to start searching +from. Defaults to 0. +<4> Set the `size` option that determines the number of search hits to return. +Defaults to 10. +<5> Set an optional timeout that controls how long the search is allowed to +take. -==== Accessing SearchResponse details +After this, the `SearchSourceBuilder` only needs to be added to the +`SearchRequest`: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-source-setter] +-------------------------------------------------- + + +[[java-rest-high-document-search-sync]] +==== Synchronous Execution + +When executing a `SearchRequest` in the following manner, the client waits +for the `SearchResponse` to be returned before continuing with code execution: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-execute] +-------------------------------------------------- + +[[java-rest-high-document-search-async]] +==== Asynchronous Execution + + +Executing a `SearchRequest` 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 in appropriate listeners: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-execute-async] +-------------------------------------------------- +<1> Called when the execution is successfully completed. +<2> Called when the whole `SearchRequest` fails. + +==== SearchResponse + +The `SearchResponse` that is returned by executing the search provides details +about the search execution itself as well as access to the documents returned. +First, there is useful information about the request execution itself, like the +HTTP status code, execution time or wether the request terminated early or timed +out: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-1] +-------------------------------------------------- + +Second, the response also provides information about the execution on the +shard level by offering statistics about the total number of shards that were +affected by the search, and the successful vs. unsuccessful shards. Possible +failures can also be handled by iterating over an array off +`ShardSearchFailures` like in the following example: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-2] +-------------------------------------------------- + +To get access to the returned documents, we need to first get the `SearchHits` +contained in the response: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-get] +-------------------------------------------------- + +The `SearchHits` provides global information about all hits, like total number +of hits or the maximum score: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-info] +-------------------------------------------------- + +Nested inside the `SearchHits` are the individual search results that can +be iterated over like this: + + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-singleHit] +-------------------------------------------------- -The `SearchResponse` that is returned by performing `client.search(searchRequest)` provides details about the search execution as well as access to the document returned as a result. First, lets look at some of the information provided by the `SearchResponse` itself: +The `SearchHit` provides access to basic information like index, type, docId and +score of each search hit: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SearchDocumentationIT.java[search-response-details] +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-singleHit-properties] -------------------------------------------------- -<1> The HTTP status code -<2> Information about query execution time, early termination or timeouts -<3> Information about successful and failed shards for this search -<4> Possible failures could be handled here -To get access to the returned documents, we need to first get the `SearchHits` contained in the response after which we -can iterate over the individual documents and can access their score and the document source: +Furthermore, it lets you get back the document source, either as a simple +JSON-String or as a map of key/value pairs. In this map, regular fields +are keyed by the field name and contain the field value. Multi-valued fields are +returned as lists of objects, nested objects as another key/value map. These +cases need to be case accordingly: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-details] +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-hits-singleHit-source] -------------------------------------------------- -<1> Get the `SearchHits` -<2> Get some global information about all hits, like total number of hits or the maximum score -<3> Iterate over the result documents -<4> Access basic information like index, type, docId and score of each search hit -<5> Access document source as a JSON string -<6> Alternatively, access document source as key/value map. -<7> Get regular field from sourceMap using the fields name. -<8> Multi-valued fields are returned as lists of objects and need to be cast accordingly -<9> Nested objects are returned as another key/value map and need to be cast accordingly