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 new file mode 100644 index 00000000000..9f86bb5c12c --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java @@ -0,0 +1,184 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.documentation; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.ClearScrollRequest; +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.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.rest.RestStatus; +import org.elasticsearch.search.Scroll; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.builder.SearchSourceBuilder; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static org.elasticsearch.index.query.QueryBuilders.matchQuery; +import static org.hamcrest.Matchers.greaterThan; + +/** + * This class is used to generate the Java High Level REST Client Search API documentation. + *

+ * You need to wrap your code between two tags like: + * // tag::example[] + * // end::example[] + *

+ * Where example is your tag name. + *

+ * Then in the documentation, you can extract what is between tag and end tags with + * ["source","java",subs="attributes,callouts,macros"] + * -------------------------------------------------- + * include-tagged::{doc-tests}/SearchDocumentationIT.java[example] + * -------------------------------------------------- + */ +public class SearchDocumentationIT extends ESRestHighLevelClientTestCase { + + public void testScroll() 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?")); + request.add(new IndexRequest("posts", "doc", "2") + .source(XContentType.JSON, "title", "Current status and upcoming changes in Elasticsearch")); + request.add(new IndexRequest("posts", "doc", "3") + .source(XContentType.JSON, "title", "The Future of Federated Search in Elasticsearch")); + request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); + BulkResponse bulkResponse = client.bulk(request); + assertSame(bulkResponse.status(), RestStatus.OK); + assertFalse(bulkResponse.hasFailures()); + } + { + // tag::search-scroll-example + final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L)); // <1> + + SearchRequest searchRequest = new SearchRequest("posts"); // <2> + searchRequest.source(new SearchSourceBuilder().query(matchQuery("title", "Elasticsearch"))); + searchRequest.scroll(scroll); // <3> + + SearchResponse searchResponse = client.search(searchRequest); // <4> + String scrollId = searchResponse.getScrollId(); // <5> + + SearchHit[] searchHits = searchResponse.getHits().getHits(); // <6> + while (searchHits != null && searchHits.length > 0) { // <7> + SearchScrollRequest scrollRequest = new SearchScrollRequest() // <8> + .scroll(scroll) // <9> + .scrollId(scrollId); // <10> + + searchResponse = client.searchScroll(scrollRequest); // <11> + scrollId = searchResponse.getScrollId(); // <12> + searchHits = searchResponse.getHits().getHits(); // <13> + } + + ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); // <14> + clearScrollRequest.addScrollId(scrollId); + client.clearScroll(clearScrollRequest); + // end::search-scroll-example + } + { + SearchRequest searchRequest = new SearchRequest(); + searchRequest.scroll("60s"); + + SearchResponse initialSearchResponse = client.search(searchRequest); + String scrollId = initialSearchResponse.getScrollId(); + + SearchScrollRequest scrollRequest = new SearchScrollRequest(); + scrollRequest.scrollId(scrollId); + + // tag::scroll-request-scroll + scrollRequest.scroll(TimeValue.timeValueSeconds(60L)); // <1> + scrollRequest.scroll("60s"); // <2> + // end::scroll-request-scroll + + // tag::search-scroll-execute-sync + SearchResponse searchResponse = client.searchScroll(scrollRequest); + // end::search-scroll-execute-sync + + assertEquals(0, searchResponse.getFailedShards()); + assertEquals(3L, searchResponse.getHits().getTotalHits()); + + // tag::search-scroll-execute-async + client.searchScrollAsync(scrollRequest, new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }); + // end::search-scroll-execute-async + + // tag::clear-scroll-request + ClearScrollRequest request = new ClearScrollRequest(); // <1> + request.addScrollId(scrollId); // <2> + // end::clear-scroll-request + + // tag::clear-scroll-add-scroll-id + request.addScrollId(scrollId); + // end::clear-scroll-add-scroll-id + + List scrollIds = Arrays.asList(scrollId); + + // tag::clear-scroll-add-scroll-ids + request.setScrollIds(scrollIds); + // end::clear-scroll-add-scroll-ids + + // tag::clear-scroll-execute + ClearScrollResponse response = client.clearScroll(request); + // end::clear-scroll-execute + + // tag::clear-scroll-response + boolean success = response.isSucceeded(); // <1> + int released = response.getNumFreed(); // <2> + // end::clear-scroll-response + assertTrue(success); + assertThat(released, greaterThan(0)); + + // tag::clear-scroll-execute-async + client.clearScrollAsync(request, new ActionListener() { + @Override + public void onResponse(ClearScrollResponse clearScrollResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }); + // end::clear-scroll-execute-async + } + } +} diff --git a/docs/java-rest/high-level/apis.asciidoc b/docs/java-rest/high-level/apis.asciidoc index 2e503d1ac86..e5c6c9c90e2 100644 --- a/docs/java-rest/high-level/apis.asciidoc +++ b/docs/java-rest/high-level/apis.asciidoc @@ -12,6 +12,6 @@ The Java High Level REST Client supports the following APIs: * <> .Search APIs -* Search API -* Search Scroll API -* Clear Scroll API +* <> +* <> +* <> diff --git a/docs/java-rest/high-level/apis/_index.asciidoc b/docs/java-rest/high-level/apis/_index.asciidoc index 35e335e5533..8a9ee69c08c 100644 --- a/docs/java-rest/high-level/apis/_index.asciidoc +++ b/docs/java-rest/high-level/apis/_index.asciidoc @@ -147,5 +147,3 @@ same index, type and id already existed: include-tagged::{doc-tests}/CRUDDocumentationIT.java[index-optype] -------------------------------------------------- <1> The raised exception indicates that a version conflict error was returned - - diff --git a/docs/java-rest/high-level/apis/index.asciidoc b/docs/java-rest/high-level/apis/index.asciidoc index 6095400a45e..e0a8c9425e3 100644 --- a/docs/java-rest/high-level/apis/index.asciidoc +++ b/docs/java-rest/high-level/apis/index.asciidoc @@ -5,5 +5,7 @@ include::get.asciidoc[] include::delete.asciidoc[] include::update.asciidoc[] include::bulk.asciidoc[] +include::search.asciidoc[] +include::scroll.asciidoc[] :doc-tests!: diff --git a/docs/java-rest/high-level/apis/scroll.asciidoc b/docs/java-rest/high-level/apis/scroll.asciidoc new file mode 100644 index 00000000000..65fac026bc0 --- /dev/null +++ b/docs/java-rest/high-level/apis/scroll.asciidoc @@ -0,0 +1,152 @@ +[[java-rest-high-search-scroll]] +=== Search Scroll API + +The Scroll API can be used to retrieve a large number of results from +a search request. + +In order to use scrolling, several steps need to be executed in a given order: + +* At first, an initial search request with a non-null `scroll` parameter must +be executed. When processing this `SearchRequest`, Elasticsearch detects the +presence of the `scroll` parameter and keeps the search context alive during +the time defined by the parameter. Elasticsearch generates a scroll identifier +associated to this search context and returns it with the first batch of search +results in a `SearchResponse`. + +* As a second step, the initial scroll parameter and the new scroll identifier +are set in a `SearchScrollRequest`. This request is executed using the Search +Scroll API and Elasticsearch returns the second batch of results with a new + scroll identifier. This new scroll id can then be used in another `SearchScrollRequest` + to retrieve the next batch of results. This process can be repeated over and + over until no more results are returned. + +* Finally, the last scroll identifier can be deleted using the <> +in order to release the search context. + +[[java-rest-high-search-scroll-example]] +==== Example of Execution + +Here is an example of a scrolled search: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-scroll-example] +-------------------------------------------------- +<1> Define a scroll parameter as a `TimeValue` corresponding to one minute +<2> Create a new `SearchRequest`. See <> +for more information on how to build `SearchRequest`. +<3> Set the `scroll` parameter to the `SearchRequest` +<4> Execute the `SearchRequest` +<5> Retrieve the first scroll id +<6> Retrieve the first batch of search hits +<7> Iterate until there are no more search hits to process +<8> Create a new `SearchScrollRequest` +<9> Set the `scroll` parameter again to tell Elasticsearch to keep the search context +alive for another minute +<10> Set the scroll id +<11> Execute the `SearchScrollRequest` using the Search Scroll API +<12> Retrieve the next scroll id to use in upcoming requests +<13> Retrieve the next batch of search hits +<14> Clear the scroll id using the <>. + +==== Optional arguments +The following argument can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[scroll-request-scroll] +-------------------------------------------------- +<1> Scroll value (ie, the time to keep alive the search context) as a `TimeValue` +<2> Scroll value (ie, the time to keep alive the search context) as a `String` + +If no `scroll` value is set for the `SearchScrollRequest`, then the search context +will expire once the initial scroll time expired (ie, the scroll time set in the +initial search request). + +[[java-rest-high-search-scroll-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-scroll-execute-sync] +-------------------------------------------------- + +[[java-rest-high-search-scroll-async]] +==== Asynchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[search-scroll-execute-async] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument + + +[[java-rest-high-clear-scroll]] +=== Clear Scroll API + +The search contexts used by the Scroll API are automatically deleted when the scroll +times out. But it is advised to release search contexts as soon as they are not +necessary anymore using the Clear Scroll API. + +[[java-rest-high-clear-scroll-request]] +==== Clear Scroll Request + +A `ClearScrollRequest` can be created as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-request] +-------------------------------------------------- +<1> Create a new `ClearScrollRequest` +<2> Adds a scroll id to the list of scroll identifiers to clear + +==== Providing the scroll identifiers +The `ClearScrollRequest` allows to clear one or more scroll identifiers in a single request. + +The scroll identifiers can be added to the request one by one: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-add-scroll-id] +-------------------------------------------------- + +Or all together using: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-add-scroll-ids] +-------------------------------------------------- + +[[java-rest-high-clear-scroll-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-execute] +-------------------------------------------------- + +[[java-rest-high-clear-scroll-async]] +==== Asynchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-execute-async] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument + +[[java-rest-high-clear-scroll-response]] +==== Clear Scroll Response + +The returned `ClearScrollResponse` allows to retrieve information about the released + search contexts: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SearchDocumentationIT.java[clear-scroll-response] +-------------------------------------------------- +<1> Return true if the request succeeded +<2> Return the number of released search contexts diff --git a/docs/java-rest/high-level/apis/search.asciidoc b/docs/java-rest/high-level/apis/search.asciidoc new file mode 100644 index 00000000000..13215806f9b --- /dev/null +++ b/docs/java-rest/high-level/apis/search.asciidoc @@ -0,0 +1,4 @@ +[[java-rest-high-search]] +=== Search API + +To be documented.