DATAES-567 - Add aggregation support to reactive client. (#430)

Original PR: #430
This commit is contained in:
amordleq
2020-04-20 12:33:35 -04:00
committed by GitHub
parent 0afa37c8ea
commit c2eec8c74a
11 changed files with 521 additions and 2 deletions

View File

@@ -19,6 +19,10 @@ import static org.assertj.core.api.Assertions.*;
import lombok.SneakyThrows;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import reactor.test.StepVerifier;
import java.io.IOException;
@@ -67,6 +71,7 @@ import org.springframework.test.context.ContextConfiguration;
* @author Mark Paluch
* @author Peter-Josef Meisch
* @author Henrique Amaral
* @author Russell Parry
*/
@SpringIntegrationTest
@ContextConfiguration(classes = { ElasticsearchRestTemplateConfiguration.class })
@@ -656,6 +661,27 @@ public class ReactiveElasticsearchClientTests {
}).verifyComplete();
}
@Test //DATAES-567
public void aggregateReturnsAggregationResults() throws IOException {
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
Map<String, Object> jsonMap = Collections.singletonMap("properties",
Collections.singletonMap("firstname", Collections.singletonMap("type", "keyword")));
syncClient.indices().putMapping(new PutMappingRequest(INDEX_I).source(jsonMap), RequestOptions.DEFAULT);
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
searchSourceBuilder.aggregation(AggregationBuilders.terms("terms").field("firstname"));
SearchRequest request = new SearchRequest(INDEX_I) //
.source(searchSourceBuilder);
client.aggregate(request)
.as(StepVerifier::create)
.expectNextMatches(aggregation -> aggregation.getType().equals(StringTerms.NAME))
.verifyComplete();
}
private AddToIndexOfType addSourceDocument() {
return add(DOC_SOURCE);
}

View File

@@ -19,11 +19,15 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.elasticsearch.client.reactive.ReactiveMockClientTestsUtils.MockWebClientProvider.Receive.*;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.metrics.ParsedMax;
import reactor.core.publisher.Hooks;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.io.IOException;
import java.net.URI;
import java.time.Instant;
import java.util.Collections;
import org.elasticsearch.ElasticsearchStatusException;
@@ -53,6 +57,7 @@ import org.springframework.util.StreamUtils;
/**
* @author Christoph Strobl
* @author Henrique Amaral
* @author Russell Parry
*/
public class ReactiveElasticsearchClientUnitTests {
@@ -577,6 +582,83 @@ public class ReactiveElasticsearchClientUnitTests {
.verifyComplete();
}
// --> AGGREGATE
@Test // DATAES-567
public void aggregateShouldHitSearchEndpoint() {
hostProvider.when(HOST) //
.receive(Receive::json) //
.body(fromPath("aggregate-ok-no-results"));
client.search(new SearchRequest("twitter")).as(StepVerifier::create).verifyComplete();
verify(hostProvider.client(HOST)).method(HttpMethod.POST);
URI uri = hostProvider.when(HOST).captureUri();
assertThat(uri.getRawPath()).isEqualTo("/twitter/_search");
}
@Test // DATAES-567
public void aggregateShouldReturnSingleResultCorrectly() {
hostProvider.when(HOST) //
.receive(Receive::json) //
.body(fromPath("aggregate-ok-single-result"));
client.aggregate(new SearchRequest("twitter")) //
.as(StepVerifier::create) //
.consumeNextWith(aggregation -> {
assertThat(aggregation.getName()).isEqualTo("users");
assertThat(aggregation instanceof ParsedStringTerms);
ParsedStringTerms parsedStringTerms = (ParsedStringTerms) aggregation;
assertThat(parsedStringTerms.getBuckets().size()).isEqualTo(2);
assertThat(parsedStringTerms.getBucketByKey("kimchy").getDocCount()).isEqualTo(2);
assertThat(parsedStringTerms.getBucketByKey("elastic").getDocCount()).isEqualTo(1);
}).verifyComplete();
}
@Test // DATAES-567
public void aggregateShouldReturnMultipleResultsCorrectly() {
hostProvider.when(HOST) //
.receive(Receive::json) //
.body(fromPath("aggregate-ok-multiple-results"));
client.aggregate(new SearchRequest("twitter")) //
.as(StepVerifier::create) //
.consumeNextWith(aggregation -> {
assertThat(aggregation.getName()).isEqualTo("users");
assertThat(aggregation instanceof ParsedStringTerms);
ParsedStringTerms parsedStringTerms = (ParsedStringTerms) aggregation;
assertThat(parsedStringTerms.getBuckets().size()).isEqualTo(2);
assertThat(parsedStringTerms.getBucketByKey("kimchy").getDocCount()).isEqualTo(2);
assertThat(parsedStringTerms.getBucketByKey("elastic").getDocCount()).isEqualTo(1);
}) //
.consumeNextWith(aggregation -> {
assertThat(aggregation.getName()).isEqualTo("max_post_date");
assertThat(aggregation instanceof ParsedMax);
ParsedMax parsedMax = (ParsedMax) aggregation;
assertThat(Instant.ofEpochMilli((long)parsedMax.getValue())).isEqualTo(Instant.parse("2010-01-15T01:46:38Z"));
}).verifyComplete();
}
@Test // DATAES-567
public void aggregateShouldReturnAggregationWithNoValuesWhenNoResultsFound() {
hostProvider.when(HOST) //
.receive(Receive::json) //
.body(fromPath("aggregate-ok-no-results"));
client.aggregate(new SearchRequest("twitter")) //
.as(StepVerifier::create) //
.consumeNextWith(aggregation -> {
assertThat(aggregation.getName()).isEqualTo("users");
assertThat(aggregation instanceof ParsedStringTerms);
ParsedStringTerms parsedStringTerms = (ParsedStringTerms) aggregation;
assertThat(parsedStringTerms.getBuckets().size()).isEqualTo(0);
}).verifyComplete();
}
// --> SCROLL
@Test // DATAES-510

View File

@@ -24,6 +24,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -78,6 +80,7 @@ import org.springframework.util.StringUtils;
* @author Farid Azaza
* @author Martin Choraine
* @author Aleksei Arsenev
* @author Russell Parry
*/
@SpringIntegrationTest
public class ReactiveElasticsearchTemplateTests {
@@ -486,6 +489,41 @@ public class ReactiveElasticsearchTemplateTests {
.verifyComplete();
}
@Test // DATAES-567
public void aggregateShouldReturnAggregations() {
SampleEntity sampleEntity1 = randomEntity("some message");
SampleEntity sampleEntity2 = randomEntity("some message");
SampleEntity sampleEntity3 = randomEntity("other message");
index(sampleEntity1, sampleEntity2, sampleEntity3);
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.addAggregation(AggregationBuilders.terms("messages").field("message"))
.build();
template.aggregate(query, SampleEntity.class) //
.as(StepVerifier::create) //
.consumeNextWith(aggregation -> {
assertThat(aggregation.getName()).isEqualTo("messages");
assertThat(aggregation instanceof ParsedStringTerms);
ParsedStringTerms parsedStringTerms = (ParsedStringTerms) aggregation;
assertThat(parsedStringTerms.getBuckets().size()).isEqualTo(3);
assertThat(parsedStringTerms.getBucketByKey("message").getDocCount()).isEqualTo(3);
assertThat(parsedStringTerms.getBucketByKey("some").getDocCount()).isEqualTo(2);
assertThat(parsedStringTerms.getBucketByKey("other").getDocCount()).isEqualTo(1);
}).verifyComplete();
}
@Test // DATAES-567
public void aggregateShouldReturnEmptyWhenIndexDoesNotExist() {
template.aggregate(new CriteriaQuery(Criteria.where("message").is("some message")), SampleEntity.class,
IndexCoordinates.of("no-such-index")) //
.as(StepVerifier::create) //
.verifyComplete();
}
@Test // DATAES-519
public void countShouldReturnZeroWhenIndexDoesNotExist() {