diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/RequestConverter.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/RequestConverter.java index 3714885b1..e854573fa 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/elc/RequestConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/RequestConverter.java @@ -1192,6 +1192,13 @@ class RequestConverter { builder.searchType(searchType(query.getSearchType())); + addHighlight(query, builder); + + if (query instanceof NativeQuery) { + prepareNativeSearch((NativeQuery) query, builder); + } + // query.getSort() must be checked after prepareNativeSearch as this already might hav a sort set that must have + // higher priority if (query.getSort() != null) { List sortOptions = getSortOptions(query.getSort(), persistentEntity); @@ -1200,12 +1207,6 @@ class RequestConverter { } } - addHighlight(query, builder); - - if (query instanceof NativeQuery) { - prepareNativeSearch((NativeQuery) query, builder); - } - if (query.getTrackTotalHits() != null) { // logic from the RHLC, choose between -1 and Integer.MAX_VALUE int value = query.getTrackTotalHits() ? Integer.MAX_VALUE : -1; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchELCIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchELCIntegrationTests.java index ff47d85f4..d550bb6fd 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchELCIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchELCIntegrationTests.java @@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.elasticsearch.client.elc.QueryBuilders.*; +import co.elastic.clients.elasticsearch._types.SortOrder; import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; import co.elastic.clients.elasticsearch._types.aggregations.Buckets; import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate; @@ -27,10 +28,13 @@ import co.elastic.clients.elasticsearch.core.search.FieldCollapse; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.elasticsearch.ELCQueries; +import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.client.elc.Aggregation; import org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregation; import org.springframework.data.elasticsearch.client.elc.NativeQuery; @@ -48,6 +52,51 @@ import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes = ReactiveElasticsearchELCIntegrationTests.Config.class) public class ReactiveElasticsearchELCIntegrationTests extends ReactiveElasticsearchIntegrationTests { + @Test // #2745 + @DisplayName("should use sort defined in native unbounded query") + void shouldUseSortDefinedInNativeUnboundedQuery() { + var entity1 = randomEntity(null); + entity1.setRate(7); + var entity2 = randomEntity(null); + entity2.setRate(5); + var entity3 = randomEntity(null); + entity3.setRate(11); + + operations.saveAll(List.of(entity1, entity2, entity3), SampleEntity.class).blockLast(); + + var query = NativeQuery.builder() + .withQuery(qb -> qb + .matchAll(m -> m)) + .withSort(sob -> sob + .field(f -> f + .field("rate") + .order(SortOrder.Asc))) + .withPageable(Pageable.unpaged()) + .build(); + + var rates = operations.search(query, SampleEntity.class) + .map(SearchHit::getContent) + .map(SampleEntity::getRate) + .collectList().block(); + assertThat(rates).containsExactly(5, 7, 11); + + query = NativeQuery.builder() + .withQuery(qb -> qb + .matchAll(m -> m)) + .withSort(sob -> sob + .field(f -> f + .field("rate") + .order(SortOrder.Desc))) + .withPageable(Pageable.unpaged()) + .build(); + + rates = operations.search(query, SampleEntity.class) + .map(SearchHit::getContent) + .map(SampleEntity::getRate) + .collectList().block(); + assertThat(rates).containsExactly(11, 7, 5); + } + @Configuration @Import({ ReactiveElasticsearchTemplateConfiguration.class }) static class Config { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchIntegrationTests.java index ffad609fd..7a414a3bf 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchIntegrationTests.java @@ -96,7 +96,7 @@ import org.springframework.util.StringUtils; @SpringIntegrationTest public abstract class ReactiveElasticsearchIntegrationTests { - @Autowired private ReactiveElasticsearchOperations operations; + @Autowired protected ReactiveElasticsearchOperations operations; @Autowired private IndexNameProvider indexNameProvider; // region Setup @@ -1165,7 +1165,7 @@ public abstract class ReactiveElasticsearchIntegrationTests { // endregion // region Helper functions - private SampleEntity randomEntity(String message) { + protected SampleEntity randomEntity(@Nullable String message) { SampleEntity entity = new SampleEntity(); entity.setId(UUID.randomUUID().toString());