Skip to content

Commit 8c59e43

Browse files
authored
Docs: HighLevelRestClient#multiSearch (#29144)
Adds docs for `HighLevelRestClient#multiSearch`. Unlike the `multiGet` docs these are much more sparse because multi-search doesn't support setting many options on the `MultiSearchRequest` and instead just wraps a list of `SearchRequest`s. Closes #28389
1 parent fede633 commit 8c59e43

File tree

4 files changed

+186
-34
lines changed

4 files changed

+186
-34
lines changed

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.elasticsearch.action.index.IndexResponse;
2828
import org.elasticsearch.action.search.ClearScrollRequest;
2929
import org.elasticsearch.action.search.ClearScrollResponse;
30+
import org.elasticsearch.action.search.MultiSearchRequest;
31+
import org.elasticsearch.action.search.MultiSearchResponse;
3032
import org.elasticsearch.action.search.SearchRequest;
3133
import org.elasticsearch.action.search.SearchResponse;
3234
import org.elasticsearch.action.search.SearchScrollRequest;
@@ -85,45 +87,15 @@
8587
import static org.hamcrest.Matchers.greaterThan;
8688

8789
/**
88-
* This class is used to generate the Java High Level REST Client Search API documentation.
89-
* <p>
90-
* You need to wrap your code between two tags like:
91-
* // tag::example
92-
* // end::example
93-
* <p>
94-
* Where example is your tag name.
95-
* <p>
96-
* Then in the documentation, you can extract what is between tag and end tags with
97-
* ["source","java",subs="attributes,callouts,macros"]
98-
* --------------------------------------------------
99-
* include-tagged::{doc-tests}/SearchDocumentationIT.java[example]
100-
* --------------------------------------------------
101-
* <p>
102-
* The column width of the code block is 84. If the code contains a line longer
103-
* than 84, the line will be cut and a horizontal scroll bar will be displayed.
104-
* (the code indentation of the tag is not included in the width)
90+
* Documentation for search APIs in the high level java client.
91+
* Code wrapped in {@code tag} and {@code end} tags is included in the docs.
10592
*/
10693
public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
10794

10895
@SuppressWarnings({"unused", "unchecked"})
10996
public void testSearch() throws Exception {
97+
indexSearchTestData();
11098
RestHighLevelClient client = highLevelClient();
111-
{
112-
BulkRequest request = new BulkRequest();
113-
request.add(new IndexRequest("posts", "doc", "1")
114-
.source(XContentType.JSON, "title", "In which order are my Elasticsearch queries executed?", "user",
115-
Arrays.asList("kimchy", "luca"), "innerObject", Collections.singletonMap("key", "value")));
116-
request.add(new IndexRequest("posts", "doc", "2")
117-
.source(XContentType.JSON, "title", "Current status and upcoming changes in Elasticsearch", "user",
118-
Arrays.asList("kimchy", "christoph"), "innerObject", Collections.singletonMap("key", "value")));
119-
request.add(new IndexRequest("posts", "doc", "3")
120-
.source(XContentType.JSON, "title", "The Future of Federated Search in Elasticsearch", "user",
121-
Arrays.asList("kimchy", "tanguy"), "innerObject", Collections.singletonMap("key", "value")));
122-
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
123-
BulkResponse bulkResponse = client.bulk(request);
124-
assertSame(RestStatus.OK, bulkResponse.status());
125-
assertFalse(bulkResponse.hasFailures());
126-
}
12799
{
128100
// tag::search-request-basic
129101
SearchRequest searchRequest = new SearchRequest(); // <1>
@@ -715,4 +687,90 @@ public void onFailure(Exception e) {
715687
assertTrue(succeeded);
716688
}
717689
}
690+
691+
public void testMultiSearch() throws Exception {
692+
indexSearchTestData();
693+
RestHighLevelClient client = highLevelClient();
694+
{
695+
// tag::multi-search-request-basic
696+
MultiSearchRequest request = new MultiSearchRequest(); // <1>
697+
SearchRequest firstSearchRequest = new SearchRequest(); // <2>
698+
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
699+
searchSourceBuilder.query(QueryBuilders.matchQuery("user", "kimchy"));
700+
firstSearchRequest.source(searchSourceBuilder);
701+
request.add(firstSearchRequest); // <3>
702+
SearchRequest secondSearchRequest = new SearchRequest(); // <4>
703+
searchSourceBuilder = new SearchSourceBuilder();
704+
searchSourceBuilder.query(QueryBuilders.matchQuery("user", "luca"));
705+
secondSearchRequest.source(searchSourceBuilder);
706+
request.add(secondSearchRequest);
707+
// end::multi-search-request-basic
708+
// tag::multi-search-execute
709+
MultiSearchResponse response = client.multiSearch(request);
710+
// end::multi-search-execute
711+
// tag::multi-search-response
712+
MultiSearchResponse.Item firstResponse = response.getResponses()[0]; // <1>
713+
assertNull(firstResponse.getFailure()); // <2>
714+
SearchResponse searchResponse = firstResponse.getResponse(); // <3>
715+
assertEquals(3, searchResponse.getHits().getTotalHits());
716+
MultiSearchResponse.Item secondResponse = response.getResponses()[1]; // <4>
717+
assertNull(secondResponse.getFailure());
718+
searchResponse = secondResponse.getResponse();
719+
assertEquals(1, searchResponse.getHits().getTotalHits());
720+
// end::multi-search-response
721+
722+
// tag::multi-search-execute-listener
723+
ActionListener<MultiSearchResponse> listener = new ActionListener<MultiSearchResponse>() {
724+
@Override
725+
public void onResponse(MultiSearchResponse response) {
726+
// <1>
727+
}
728+
729+
@Override
730+
public void onFailure(Exception e) {
731+
// <2>
732+
}
733+
};
734+
// end::multi-search-execute-listener
735+
736+
// Replace the empty listener by a blocking listener in test
737+
final CountDownLatch latch = new CountDownLatch(1);
738+
listener = new LatchedActionListener<>(listener, latch);
739+
740+
// tag::multi-search-execute-async
741+
client.multiSearchAsync(request, listener); // <1>
742+
// end::multi-search-execute-async
743+
744+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
745+
}
746+
{
747+
// tag::multi-search-request-index
748+
MultiSearchRequest request = new MultiSearchRequest();
749+
request.add(new SearchRequest("posts") // <1>
750+
.types("doc")); // <2>
751+
// end::multi-search-request-index
752+
MultiSearchResponse response = client.multiSearch(request);
753+
MultiSearchResponse.Item firstResponse = response.getResponses()[0];
754+
assertNull(firstResponse.getFailure());
755+
SearchResponse searchResponse = firstResponse.getResponse();
756+
assertEquals(3, searchResponse.getHits().getTotalHits());
757+
}
758+
}
759+
760+
private void indexSearchTestData() throws IOException {
761+
BulkRequest request = new BulkRequest();
762+
request.add(new IndexRequest("posts", "doc", "1")
763+
.source(XContentType.JSON, "title", "In which order are my Elasticsearch queries executed?", "user",
764+
Arrays.asList("kimchy", "luca"), "innerObject", Collections.singletonMap("key", "value")));
765+
request.add(new IndexRequest("posts", "doc", "2")
766+
.source(XContentType.JSON, "title", "Current status and upcoming changes in Elasticsearch", "user",
767+
Arrays.asList("kimchy", "christoph"), "innerObject", Collections.singletonMap("key", "value")));
768+
request.add(new IndexRequest("posts", "doc", "3")
769+
.source(XContentType.JSON, "title", "The Future of Federated Search in Elasticsearch", "user",
770+
Arrays.asList("kimchy", "tanguy"), "innerObject", Collections.singletonMap("key", "value")));
771+
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
772+
BulkResponse bulkResponse = highLevelClient().bulk(request);
773+
assertSame(RestStatus.OK, bulkResponse.status());
774+
assertFalse(bulkResponse.hasFailures());
775+
}
718776
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
[[java-rest-high-multi-search]]
2+
=== Multi-Search API
3+
4+
The `multiSearch` API executes multiple <<java-rest-high-search,`search`>>
5+
requests in a single http request in parallel.
6+
7+
[[java-rest-high-multi-search-request]]
8+
==== Multi-Search Request
9+
10+
The `MultiSearchRequest` is built empty and you add all of the searches that
11+
you wish to execute to it:
12+
13+
["source","java",subs="attributes,callouts,macros"]
14+
--------------------------------------------------
15+
include-tagged::{doc-tests}/SearchDocumentationIT.java[multi-search-request-basic]
16+
--------------------------------------------------
17+
<1> Create an empty `MultiSearchRequest`.
18+
<2> Create an empty `SearchRequest` and populate it just like you
19+
would for a regular <<java-rest-high-search,`search`>>.
20+
<3> Add the `SearchRequest` to the `MultiSearchRequest`.
21+
<4> Build a second `SearchRequest` and add it to the `MultiSearchRequest`.
22+
23+
===== Optional arguments
24+
25+
The `SearchRequest`s inside of `MultiSearchRequest` support all of
26+
<<java-rest-high-search-request-optional,`search`>>'s optional arguments.
27+
For example:
28+
29+
["source","java",subs="attributes,callouts,macros"]
30+
--------------------------------------------------
31+
include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-indices-types]
32+
--------------------------------------------------
33+
<1> Restricts the request to an index
34+
<2> Limits the request to a type
35+
36+
[[java-rest-high-multi-search-sync]]
37+
==== Synchronous Execution
38+
39+
The `multiSearch` method executes `MultiSearchRequest`s synchronously:
40+
41+
["source","java",subs="attributes,callouts,macros"]
42+
--------------------------------------------------
43+
include-tagged::{doc-tests}/SearchDocumentationIT.java[multi-search-execute]
44+
--------------------------------------------------
45+
46+
[[java-rest-high-multi-search-async]]
47+
==== Asynchronous Execution
48+
49+
The `multiSearchAsync` method executes `MultiSearchRequest`s asynchronously,
50+
calling the provided `ActionListener` when the response is ready.
51+
52+
["source","java",subs="attributes,callouts,macros"]
53+
--------------------------------------------------
54+
include-tagged::{doc-tests}/SearchDocumentationIT.java[search-execute-async]
55+
--------------------------------------------------
56+
<1> The `MultiSearchRequest` to execute and the `ActionListener` to use when
57+
the execution completes
58+
59+
The asynchronous method does not block and returns immediately. Once it is
60+
completed the `ActionListener` is called back using the `onResponse` method
61+
if the execution successfully completed or using the `onFailure` method if
62+
it failed.
63+
64+
A typical listener for `MultiSearchResponse` looks like:
65+
66+
["source","java",subs="attributes,callouts,macros"]
67+
--------------------------------------------------
68+
include-tagged::{doc-tests}/SearchDocumentationIT.java[multi-search-execute-listener]
69+
--------------------------------------------------
70+
<1> Called when the execution is successfully completed.
71+
<2> Called when the whole `SearchRequest` fails.
72+
73+
==== MultiSearchResponse
74+
75+
The `MultiSearchResponse` that is returned by executing the `multiSearch`
76+
a `MultiSearchResponse.Item` for each `SearchRequest` in the
77+
`MultiSearchRequest`. Each `MultiSearchResponse.Item` contains an
78+
exception in `getFailure` if the request failed or a
79+
<<java-rest-high-search-response,`SearchResponse`>> in `getResponse` if
80+
the request succeeded:
81+
82+
["source","java",subs="attributes,callouts,macros"]
83+
--------------------------------------------------
84+
include-tagged::{doc-tests}/SearchDocumentationIT.java[multi-search-response]
85+
--------------------------------------------------
86+
<1> The item for the first search.
87+
<2> It succeeded so `getFailure` returns null.
88+
<3> And there is a <<java-rest-high-search-response,`SearchResponse`>> in
89+
`getResponse`.
90+
<4> The item for the second search.

docs/java-rest/high-level/search/search.asciidoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-basic]
2020
<3> Add a `match_all` query to the `SearchSourceBuilder`.
2121
<4> Add the `SearchSourceBuilder` to the `SeachRequest`.
2222

23+
[[java-rest-high-search-request-optional]]
2324
===== Optional arguments
2425

2526
Let's first look at some of the optional arguments of a `SearchRequest`:
@@ -140,7 +141,7 @@ The `SearchSourceBuilder` allows to add one or more `SortBuilder` instances. The
140141
include-tagged::{doc-tests}/SearchDocumentationIT.java[search-source-sorting]
141142
--------------------------------------------------
142143
<1> Sort descending by `_score` (the default)
143-
<2> Also sort ascending by `_id` field
144+
<2> Also sort ascending by `_id` field
144145

145146
===== Source filtering
146147

@@ -268,6 +269,7 @@ include-tagged::{doc-tests}/SearchDocumentationIT.java[search-execute-listener]
268269
<1> Called when the execution is successfully completed.
269270
<2> Called when the whole `SearchRequest` fails.
270271

272+
[[java-rest-high-search-response]]
271273
==== SearchResponse
272274

273275
The `SearchResponse` that is returned by executing the search provides details

docs/java-rest/high-level/supported-apis.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ The Java High Level REST Client supports the following Search APIs:
3131
* <<java-rest-high-search>>
3232
* <<java-rest-high-search-scroll>>
3333
* <<java-rest-high-clear-scroll>>
34+
* <<java-rest-high-multi-search>>
3435

3536
include::search/search.asciidoc[]
3637
include::search/scroll.asciidoc[]
38+
include::search/multi-search.asciidoc[]
3739

3840
== Miscellaneous APIs
3941

0 commit comments

Comments
 (0)