Skip to content

Commit 2efb892

Browse files
mrdjenhub-cap
authored andcommitted
HLRC: Add document _count API (#34267)
Add `count()` api method, `CountRequest` and `CountResponse` classes to HLRC. Code in server module is unchanged. Relates to #27205
1 parent 16c7bcc commit 2efb892

File tree

12 files changed

+1073
-1
lines changed

12 files changed

+1073
-1
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.elasticsearch.action.support.IndicesOptions;
5050
import org.elasticsearch.action.support.WriteRequest;
5151
import org.elasticsearch.action.update.UpdateRequest;
52+
import org.elasticsearch.client.core.CountRequest;
5253
import org.elasticsearch.client.security.RefreshPolicy;
5354
import org.elasticsearch.cluster.health.ClusterHealthStatus;
5455
import org.elasticsearch.common.Nullable;
@@ -448,6 +449,16 @@ static Request multiSearchTemplate(MultiSearchTemplateRequest multiSearchTemplat
448449
return request;
449450
}
450451

452+
static Request count(CountRequest countRequest) throws IOException {
453+
Request request = new Request(HttpPost.METHOD_NAME, endpoint(countRequest.indices(), countRequest.types(), "_count"));
454+
Params params = new Params(request);
455+
params.withRouting(countRequest.routing());
456+
params.withPreference(countRequest.preference());
457+
params.withIndicesOptions(countRequest.indicesOptions());
458+
request.setEntity(createEntity(countRequest.source(), REQUEST_BODY_CONTENT_TYPE));
459+
return request;
460+
}
461+
451462
static Request explain(ExplainRequest explainRequest) throws IOException {
452463
Request request = new Request(HttpGet.METHOD_NAME,
453464
endpoint(explainRequest.index(), explainRequest.type(), explainRequest.id(), "_explain"));

client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
import org.elasticsearch.action.support.master.AcknowledgedResponse;
5858
import org.elasticsearch.action.update.UpdateRequest;
5959
import org.elasticsearch.action.update.UpdateResponse;
60+
import org.elasticsearch.client.core.CountRequest;
61+
import org.elasticsearch.client.core.CountResponse;
6062
import org.elasticsearch.client.core.TermVectorsResponse;
6163
import org.elasticsearch.client.core.TermVectorsRequest;
6264
import org.elasticsearch.common.CheckedConsumer;
@@ -923,6 +925,31 @@ public final void indexAsync(IndexRequest indexRequest, ActionListener<IndexResp
923925
emptySet(), headers);
924926
}
925927

928+
/**
929+
* Executes a count request using the Count API.
930+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html">Count API on elastic.co</a>
931+
* @param countRequest the request
932+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
933+
* @return the response
934+
* @throws IOException in case there is a problem sending the request or parsing back the response
935+
*/
936+
public final CountResponse count(CountRequest countRequest, RequestOptions options) throws IOException {
937+
return performRequestAndParseEntity(countRequest, RequestConverters::count, options, CountResponse::fromXContent,
938+
emptySet());
939+
}
940+
941+
/**
942+
* Asynchronously executes a count request using the Count API.
943+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html">Count API on elastic.co</a>
944+
* @param countRequest the request
945+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
946+
* @param listener the listener to be notified upon request completion
947+
*/
948+
public final void countAsync(CountRequest countRequest, RequestOptions options, ActionListener<CountResponse> listener) {
949+
performRequestAsyncAndParseEntity(countRequest, RequestConverters::count, options,CountResponse::fromXContent,
950+
listener, emptySet());
951+
}
952+
926953
/**
927954
* Updates a document using the Update API.
928955
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html">Update API on elastic.co</a>
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.core;
21+
22+
import org.elasticsearch.action.ActionRequest;
23+
import org.elasticsearch.action.ActionRequestValidationException;
24+
import org.elasticsearch.action.IndicesRequest;
25+
import org.elasticsearch.action.support.IndicesOptions;
26+
import org.elasticsearch.common.Strings;
27+
import org.elasticsearch.search.builder.SearchSourceBuilder;
28+
29+
import java.util.Arrays;
30+
import java.util.Objects;
31+
32+
import static org.elasticsearch.action.search.SearchRequest.DEFAULT_INDICES_OPTIONS;
33+
34+
/**
35+
* Encapsulates a request to _count API against one, several or all indices.
36+
*/
37+
public final class CountRequest extends ActionRequest implements IndicesRequest.Replaceable {
38+
39+
private String[] indices = Strings.EMPTY_ARRAY;
40+
private String[] types = Strings.EMPTY_ARRAY;
41+
private String routing;
42+
private String preference;
43+
private SearchSourceBuilder searchSourceBuilder;
44+
private IndicesOptions indicesOptions = DEFAULT_INDICES_OPTIONS;
45+
46+
public CountRequest() {
47+
this.searchSourceBuilder = new SearchSourceBuilder();
48+
}
49+
50+
/**
51+
* Constructs a new count request against the indices. No indices provided here means that count will execute on all indices.
52+
*/
53+
public CountRequest(String... indices) {
54+
this(indices, new SearchSourceBuilder());
55+
}
56+
57+
/**
58+
* Constructs a new search request against the provided indices with the given search source.
59+
*/
60+
public CountRequest(String[] indices, SearchSourceBuilder searchSourceBuilder) {
61+
indices(indices);
62+
this.searchSourceBuilder = searchSourceBuilder;
63+
}
64+
65+
@Override
66+
public ActionRequestValidationException validate() {
67+
return null;
68+
}
69+
70+
/**
71+
* Sets the indices the count will be executed on.
72+
*/
73+
public CountRequest indices(String... indices) {
74+
Objects.requireNonNull(indices, "indices must not be null");
75+
for (String index : indices) {
76+
Objects.requireNonNull(index, "index must not be null");
77+
}
78+
this.indices = indices;
79+
return this;
80+
}
81+
82+
/**
83+
* The source of the count request.
84+
*/
85+
public CountRequest source(SearchSourceBuilder searchSourceBuilder) {
86+
this.searchSourceBuilder = Objects.requireNonNull(searchSourceBuilder, "source must not be null");
87+
return this;
88+
}
89+
90+
/**
91+
* The document types to execute the count against. Defaults to be executed against all types.
92+
*
93+
* @deprecated Types are going away, prefer filtering on a type.
94+
*/
95+
@Deprecated
96+
public CountRequest types(String... types) {
97+
Objects.requireNonNull(types, "types must not be null");
98+
for (String type : types) {
99+
Objects.requireNonNull(type, "type must not be null");
100+
}
101+
this.types = types;
102+
return this;
103+
}
104+
105+
/**
106+
* The routing values to control the shards that the search will be executed on.
107+
*/
108+
public CountRequest routing(String routing) {
109+
this.routing = routing;
110+
return this;
111+
}
112+
113+
/**
114+
* A comma separated list of routing values to control the shards the count will be executed on.
115+
*/
116+
public CountRequest routing(String... routings) {
117+
this.routing = Strings.arrayToCommaDelimitedString(routings);
118+
return this;
119+
}
120+
121+
/**
122+
* Returns the indices options used to resolve indices. They tell for instance whether a single index is accepted, whether an empty
123+
* array will be converted to _all, and how wildcards will be expanded if needed.
124+
*
125+
* @see org.elasticsearch.action.support.IndicesOptions
126+
*/
127+
public CountRequest indicesOptions(IndicesOptions indicesOptions) {
128+
this.indicesOptions = Objects.requireNonNull(indicesOptions, "indicesOptions must not be null");
129+
return this;
130+
}
131+
132+
/**
133+
* Sets the preference to execute the count. Defaults to randomize across shards. Can be set to {@code _local} to prefer local shards
134+
* or a custom value, which guarantees that the same order will be used across different requests.
135+
*/
136+
public CountRequest preference(String preference) {
137+
this.preference = preference;
138+
return this;
139+
}
140+
141+
public IndicesOptions indicesOptions() {
142+
return this.indicesOptions;
143+
}
144+
145+
public String routing() {
146+
return this.routing;
147+
}
148+
149+
public String preference() {
150+
return this.preference;
151+
}
152+
153+
public String[] indices() {
154+
return Arrays.copyOf(this.indices, this.indices.length);
155+
}
156+
157+
public Float minScore() {
158+
return this.searchSourceBuilder.minScore();
159+
}
160+
161+
public CountRequest minScore(Float minScore) {
162+
this.searchSourceBuilder.minScore(minScore);
163+
return this;
164+
}
165+
166+
public int terminateAfter() {
167+
return this.searchSourceBuilder.terminateAfter();
168+
}
169+
170+
public CountRequest terminateAfter(int terminateAfter) {
171+
this.searchSourceBuilder.terminateAfter(terminateAfter);
172+
return this;
173+
}
174+
175+
public String[] types() {
176+
return Arrays.copyOf(this.types, this.types.length);
177+
}
178+
179+
public SearchSourceBuilder source() {
180+
return this.searchSourceBuilder;
181+
}
182+
183+
@Override
184+
public boolean equals(Object o) {
185+
if (this == o) {
186+
return true;
187+
}
188+
if (o == null || getClass() != o.getClass()) {
189+
return false;
190+
}
191+
CountRequest that = (CountRequest) o;
192+
return Objects.equals(indicesOptions, that.indicesOptions) &&
193+
Arrays.equals(indices, that.indices) &&
194+
Arrays.equals(types, that.types) &&
195+
Objects.equals(routing, that.routing) &&
196+
Objects.equals(preference, that.preference);
197+
}
198+
199+
@Override
200+
public int hashCode() {
201+
int result = Objects.hash(indicesOptions, routing, preference);
202+
result = 31 * result + Arrays.hashCode(indices);
203+
result = 31 * result + Arrays.hashCode(types);
204+
return result;
205+
}
206+
}

0 commit comments

Comments
 (0)