Adding basic search request documentation for high level client (#25651)
This commit is contained in:
parent
d2b4f7ac5a
commit
f3e7a1c4a4
|
@ -28,20 +28,28 @@ import org.elasticsearch.action.search.ClearScrollResponse;
|
|||
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;
|
||||
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 +71,134 @@ import static org.hamcrest.Matchers.greaterThan;
|
|||
*/
|
||||
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 {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
|
|
|
@ -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() {
|
||||
if (this.source == null) {
|
||||
|
|
|
@ -1,4 +1,180 @@
|
|||
[[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 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]
|
||||
--------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue