Adding basic search request documentation for high level client (#25651)

This commit is contained in:
Christoph Büscher 2017-07-12 17:06:46 +02:00 committed by GitHub
parent d2b4f7ac5a
commit f3e7a1c4a4
3 changed files with 314 additions and 2 deletions

View File

@ -28,20 +28,28 @@ import org.elasticsearch.action.search.ClearScrollResponse;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest; 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.action.support.WriteRequest;
import org.elasticsearch.client.ESRestHighLevelClientTestCase; import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.Scroll; import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
@ -63,6 +71,134 @@ import static org.hamcrest.Matchers.greaterThan;
*/ */
public class SearchDocumentationIT extends ESRestHighLevelClientTestCase { 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-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));
}
{
// 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>
// end::search-source-basics
// tag::search-source-setter
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(sourceBuilder);
// end::search-source-setter
// tag::search-execute
SearchResponse searchResponse = client.search(searchRequest);
// end::search-execute
// tag::search-execute-async
client.searchAsync(searchRequest, new ActionListener<SearchResponse>() {
@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();
// end::search-response-1
// tag::search-response-2
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
// end::search-response-2
assertNotNull(searchResponse);
// 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) {
// 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();
// end::search-hits-singleHit-properties
// tag::search-hits-singleHit-source
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");
// end::search-hits-singleHit-source
}
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 { public void testScroll() throws IOException {
RestHighLevelClient client = highLevelClient(); RestHighLevelClient client = highLevelClient();
{ {

View File

@ -192,7 +192,7 @@ public final class SearchHit implements Streamable, ToXContentObject, Iterable<D
} }
/** /**
* Returns bytes reference, also un compress the source if needed. * Returns bytes reference, also uncompress the source if needed.
*/ */
public BytesReference getSourceRef() { public BytesReference getSourceRef() {
if (this.source == null) { if (this.source == null) {

View File

@ -1,4 +1,180 @@
[[java-rest-high-search]] [[java-rest-high-search]]
=== Search API === 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 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:
["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 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`.
==== 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-request-indices-types]
--------------------------------------------------
There are a couple of other interesting optional parameters:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-routing]
--------------------------------------------------
<1> Set a routing parameter
["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
["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.
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.
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 `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-hits-singleHit-properties]
--------------------------------------------------
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-singleHit-source]
--------------------------------------------------