Skip to content

Commit 86c537a

Browse files
committed
Add count methods to ELC's ReactiveElasticsearchClient.
Implemented count methods using CountRequest directly with ELC's ReactiveElasticsearchClient, eliminating the need to initialize any entity or repository. Refactored the existing doCount method in ReactiveElasticsearchTemplate to utilize the newly added count method. Closes spring-projects#2749
1 parent 98716a8 commit 86c537a

File tree

5 files changed

+164
-4
lines changed

5 files changed

+164
-4
lines changed

Diff for: src/main/java/org/springframework/data/elasticsearch/client/elc/ReactiveElasticsearchClient.java

+21
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* Reactive version of {@link co.elastic.clients.elasticsearch.ElasticsearchClient}.
3737
*
3838
* @author Peter-Josef Meisch
39+
* @author maryantocinn
3940
* @since 4.4
4041
*/
4142
public class ReactiveElasticsearchClient extends ApiClient<ElasticsearchTransport, ReactiveElasticsearchClient>
@@ -227,6 +228,26 @@ public Mono<DeleteByQueryResponse> deleteByQuery(
227228
return deleteByQuery(fn.apply(new DeleteByQueryRequest.Builder()).build());
228229
}
229230

231+
/**
232+
* @since 5.4
233+
*/
234+
public Mono<CountResponse> count(CountRequest request) {
235+
236+
Assert.notNull(request, "request must not be null");
237+
238+
return Mono.fromFuture(transport.performRequestAsync(request, CountRequest._ENDPOINT, transportOptions));
239+
}
240+
241+
/**
242+
* @since 5.4
243+
*/
244+
public Mono<CountResponse> count(Function<CountRequest.Builder, ObjectBuilder<CountRequest>> fn) {
245+
246+
Assert.notNull(fn, "fn must not be null");
247+
248+
return count(fn.apply(new CountRequest.Builder()).build());
249+
}
250+
230251
// endregion
231252
// region search
232253

Diff for: src/main/java/org/springframework/data/elasticsearch/client/elc/ReactiveElasticsearchTemplate.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
* @author Peter-Josef Meisch
7676
* @author Illia Ulianov
7777
* @author Junghoon Ban
78+
* @author maryantocinn
7879
* @since 4.4
7980
*/
8081
public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearchTemplate {
@@ -483,11 +484,10 @@ protected Mono<Long> doCount(Query query, Class<?> entityType, IndexCoordinates
483484
Assert.notNull(query, "query must not be null");
484485
Assert.notNull(index, "index must not be null");
485486

486-
SearchRequest searchRequest = requestConverter.searchRequest(query, routingResolver.getRouting(), entityType, index,
487-
true);
487+
CountRequest request = requestConverter.countRequest(query, entityType, index);
488488

489-
return Mono.from(execute(client -> client.search(searchRequest, EntityAsMap.class)))
490-
.map(searchResponse -> searchResponse.hits().total() != null ? searchResponse.hits().total().value() : 0L);
489+
return Mono.from(execute(client -> client.count(request))) //
490+
.map(CountResponse::count);
491491
}
492492

493493
private Flux<SearchDocument> doFindBounded(Query query, Class<?> clazz, IndexCoordinates index) {

Diff for: src/main/java/org/springframework/data/elasticsearch/client/elc/RequestConverter.java

+13
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
* @author cdalxndr
112112
* @author scoobyzhang
113113
* @author Haibo Liu
114+
* @author maryantocinn
114115
* @since 4.4
115116
*/
116117
class RequestConverter extends AbstractQueryProcessor {
@@ -1188,6 +1189,18 @@ public UpdateByQueryRequest documentUpdateByQueryRequest(UpdateQuery updateQuery
11881189
});
11891190
}
11901191

1192+
public <T> CountRequest countRequest(Query query, @Nullable Class<T> clazz, IndexCoordinates indexCoordinates) {
1193+
1194+
Assert.notNull(query, "query must not be null");
1195+
Assert.notNull(indexCoordinates, "index must not be null");
1196+
1197+
elasticsearchConverter.updateQuery(query, clazz);
1198+
1199+
return CountRequest.of(b -> b //
1200+
.query(getQuery(query, clazz)) //
1201+
.index(Arrays.asList(indexCoordinates.getIndexNames())));
1202+
}
1203+
11911204
// endregion
11921205

11931206
// region search
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.springframework.data.elasticsearch.core;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.context.annotation.Import;
6+
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchTemplateConfiguration;
7+
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
8+
import org.springframework.test.context.ContextConfiguration;
9+
10+
/**
11+
* @author maryantocinn
12+
* @since 5.4
13+
*/
14+
@ContextConfiguration(classes = ReactiveCountELCIntegrationTests.Config.class)
15+
public class ReactiveCountELCIntegrationTests extends ReactiveCountIntegrationTests {
16+
17+
@Configuration
18+
@Import({ ReactiveElasticsearchTemplateConfiguration.class })
19+
static class Config {
20+
@Bean
21+
IndexNameProvider indexNameProvider() {
22+
return new IndexNameProvider("reactive-count");
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package org.springframework.data.elasticsearch.core;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.Order;
5+
import org.junit.jupiter.api.Test;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.data.annotation.Id;
8+
import org.springframework.data.elasticsearch.annotations.Document;
9+
import org.springframework.data.elasticsearch.annotations.Field;
10+
import org.springframework.data.elasticsearch.annotations.FieldType;
11+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
12+
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
13+
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
14+
import org.springframework.lang.Nullable;
15+
import reactor.test.StepVerifier;
16+
17+
import static org.springframework.data.elasticsearch.core.IndexOperationsAdapter.*;
18+
import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
19+
20+
/**
21+
* Integration tests for the count API.
22+
*
23+
* @author maryantocinn
24+
* @since 5.4
25+
*/
26+
@SpringIntegrationTest
27+
public abstract class ReactiveCountIntegrationTests {
28+
29+
@Autowired private ReactiveElasticsearchOperations operations;
30+
@Autowired private IndexNameProvider indexNameProvider;
31+
32+
@BeforeEach
33+
public void beforeEach() {
34+
35+
indexNameProvider.increment();
36+
blocking(operations.indexOps(ReactiveReindexIntegrationTests.Entity.class)).createWithMapping();
37+
}
38+
39+
@Test
40+
@Order(java.lang.Integer.MAX_VALUE)
41+
void cleanup() {
42+
blocking(operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + '*'))).delete();
43+
}
44+
45+
@Test // GH-2749
46+
void shouldCount() {
47+
String indexName = indexNameProvider.indexName();
48+
49+
Entity entity = new Entity();
50+
entity.setId(nextIdAsString());
51+
entity.setMessage("abc");
52+
53+
operations.save(entity) //
54+
.as(StepVerifier::create) //
55+
.expectNextCount(1) //
56+
.verifyComplete();
57+
58+
Entity entity2 = new Entity();
59+
entity2.setId(nextIdAsString());
60+
entity2.setMessage("def");
61+
62+
operations.save(entity2) //
63+
.as(StepVerifier::create) //
64+
.expectNextCount(1) //
65+
.verifyComplete();
66+
67+
operations.count(operations.matchAllQuery(), Entity.class, IndexCoordinates.of(indexName)) //
68+
.as(StepVerifier::create) //
69+
.expectNext(2L) //
70+
.verifyComplete();
71+
}
72+
73+
74+
@Document(indexName = "#{@indexNameProvider.indexName()}")
75+
static class Entity {
76+
@Nullable
77+
@Id
78+
private String id;
79+
@Nullable
80+
@Field(type = FieldType.Text) private String message;
81+
82+
@Nullable
83+
public String getId() {
84+
return id;
85+
}
86+
87+
public void setId(@Nullable String id) {
88+
this.id = id;
89+
}
90+
91+
@Nullable
92+
public String getMessage() {
93+
return message;
94+
}
95+
96+
public void setMessage(@Nullable String message) {
97+
this.message = message;
98+
}
99+
}
100+
101+
}

0 commit comments

Comments
 (0)