Skip to content

Commit 6cfb8ee

Browse files
authored
[elc] add support for sorting results by SortOptions to NativeQuery.
Original Pull Request #2264 Closes #2263
1 parent c4910bf commit 6cfb8ee

File tree

4 files changed

+88
-5
lines changed

4 files changed

+88
-5
lines changed

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.elasticsearch.client.elc;
1717

18+
import co.elastic.clients.elasticsearch._types.SortOptions;
1819
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
1920
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
2021
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
@@ -26,7 +27,6 @@
2627
import java.util.Map;
2728

2829
import org.springframework.data.elasticsearch.core.query.BaseQuery;
29-
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
3030
import org.springframework.data.elasticsearch.core.query.ScriptedField;
3131
import org.springframework.lang.Nullable;
3232

@@ -35,6 +35,7 @@
3535
* Elasticsearch Client library.
3636
*
3737
* @author Peter-Josef Meisch
38+
* @author Sascha Woo
3839
* @since 4.4
3940
*/
4041
public class NativeQuery extends BaseQuery {
@@ -46,6 +47,7 @@ public class NativeQuery extends BaseQuery {
4647
@Nullable private Suggester suggester;
4748
@Nullable private FieldCollapse fieldCollapse;
4849
private List<ScriptedField> scriptedFields = Collections.emptyList();
50+
private List<SortOptions> sortOptions = Collections.emptyList();
4951

5052
public NativeQuery(NativeQueryBuilder builder) {
5153
super(builder);
@@ -55,6 +57,7 @@ public NativeQuery(NativeQueryBuilder builder) {
5557
this.suggester = builder.getSuggester();
5658
this.fieldCollapse = builder.getFieldCollapse();
5759
this.scriptedFields = builder.getScriptedFields();
60+
this.sortOptions = builder.getSortOptions();
5861
}
5962

6063
public NativeQuery(@Nullable Query query) {
@@ -92,4 +95,8 @@ public FieldCollapse getFieldCollapse() {
9295
public List<ScriptedField> getScriptedFields() {
9396
return scriptedFields;
9497
}
98+
99+
public List<SortOptions> getSortOptions() {
100+
return sortOptions;
101+
}
95102
}

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

+40-2
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,29 @@
1515
*/
1616
package org.springframework.data.elasticsearch.client.elc;
1717

18+
import co.elastic.clients.elasticsearch._types.SortOptions;
1819
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
1920
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
2021
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
2122
import co.elastic.clients.elasticsearch.core.search.Suggester;
2223
import co.elastic.clients.util.ObjectBuilder;
2324

2425
import java.util.ArrayList;
26+
import java.util.Arrays;
27+
import java.util.Collections;
2528
import java.util.LinkedHashMap;
2629
import java.util.List;
2730
import java.util.Map;
2831
import java.util.function.Function;
2932

3033
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
31-
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
3234
import org.springframework.data.elasticsearch.core.query.ScriptedField;
3335
import org.springframework.lang.Nullable;
3436
import org.springframework.util.Assert;
3537

3638
/**
3739
* @author Peter-Josef Meisch
40+
* @author Sascha Woo
3841
* @since 4.4
3942
*/
4043
public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQueryBuilder> {
@@ -45,7 +48,10 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
4548
@Nullable private Suggester suggester;
4649
@Nullable private FieldCollapse fieldCollapse;
4750
private final List<ScriptedField> scriptedFields = new ArrayList<>();
48-
public NativeQueryBuilder() {}
51+
private List<SortOptions> sortOptions = new ArrayList<>();
52+
53+
public NativeQueryBuilder() {
54+
}
4955

5056
@Nullable
5157
public Query getQuery() {
@@ -75,6 +81,10 @@ public List<ScriptedField> getScriptedFields() {
7581
return scriptedFields;
7682
}
7783

84+
public List<SortOptions> getSortOptions() {
85+
return sortOptions;
86+
}
87+
7888
public NativeQueryBuilder withQuery(Query query) {
7989

8090
Assert.notNull(query, "query must not be null");
@@ -129,6 +139,34 @@ public NativeQueryBuilder withScriptedField(ScriptedField scriptedField) {
129139
return this;
130140
}
131141

142+
public NativeQueryBuilder withSort(List<SortOptions> values) {
143+
144+
Assert.notEmpty(values, "values must not be empty");
145+
sortOptions.clear();
146+
sortOptions.addAll(values);
147+
148+
return this;
149+
}
150+
151+
public NativeQueryBuilder withSort(SortOptions value, SortOptions... values) {
152+
153+
Assert.notNull(value, "value must not be null");
154+
sortOptions.add(value);
155+
if (values.length > 0) {
156+
sortOptions.addAll(Arrays.asList(values));
157+
}
158+
159+
return this;
160+
}
161+
162+
public NativeQueryBuilder withSort(Function<SortOptions.Builder, ObjectBuilder<SortOptions>> fn) {
163+
164+
Assert.notNull(fn, "fn must not be null");
165+
withSort(fn.apply(new SortOptions.Builder()).build());
166+
167+
return this;
168+
}
169+
132170
public NativeQuery build() {
133171
return new NativeQuery(this);
134172
}

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
* Class to create Elasticsearch request and request builders.
102102
*
103103
* @author Peter-Josef Meisch
104+
* @author Sascha Woo
104105
* @since 4.4
105106
*/
106107
class RequestConverter {
@@ -1405,7 +1406,7 @@ private void prepareNativeSearch(NativeQuery query, SearchRequest.Builder builde
14051406
builder //
14061407
.suggest(query.getSuggester()) //
14071408
.collapse(query.getFieldCollapse()) //
1408-
;
1409+
.sort(query.getSortOptions());
14091410

14101411
if (!isEmpty(query.getAggregations())) {
14111412
builder.aggregations(query.getAggregations());
@@ -1424,7 +1425,7 @@ private void prepareNativeSearch(NativeQuery query, MultisearchBody.Builder buil
14241425
builder //
14251426
.suggest(query.getSuggester()) //
14261427
.collapse(query.getFieldCollapse()) //
1427-
;
1428+
.sort(query.getSortOptions());
14281429

14291430
if (!isEmpty(query.getAggregations())) {
14301431
builder.aggregations(query.getAggregations());

Diff for: src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchELCIntegrationTests.java

+37
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,34 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core;
1717

18+
import static org.assertj.core.api.Assertions.*;
1819
import static org.springframework.data.elasticsearch.client.elc.QueryBuilders.*;
20+
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
1921

22+
import co.elastic.clients.elasticsearch._types.SortOptionsBuilders;
23+
import co.elastic.clients.elasticsearch._types.SortOrder;
2024
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
2125
import co.elastic.clients.elasticsearch._types.query_dsl.FunctionBoostMode;
2226
import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScoreMode;
2327
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
2428
import co.elastic.clients.json.JsonData;
2529

30+
import java.util.ArrayList;
31+
import java.util.List;
2632
import java.util.Map;
2733

2834
import org.junit.jupiter.api.DisplayName;
35+
import org.junit.jupiter.api.Test;
2936
import org.springframework.context.annotation.Bean;
3037
import org.springframework.context.annotation.Configuration;
3138
import org.springframework.context.annotation.Import;
3239
import org.springframework.data.elasticsearch.ELCQueries;
3340
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
3441
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
42+
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
3543
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
3644
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
45+
import org.springframework.data.elasticsearch.core.query.IndexQuery;
3746
import org.springframework.data.elasticsearch.core.query.Query;
3847
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
3948
import org.springframework.data.elasticsearch.core.query.ScriptData;
@@ -45,6 +54,7 @@
4554

4655
/**
4756
* @author Farid Faoudi
57+
* @author Sascha Woo
4858
* @since 4.4
4959
*/
5060
@ContextConfiguration(classes = { ElasticsearchELCIntegrationTests.Config.class })
@@ -60,6 +70,33 @@ IndexNameProvider indexNameProvider() {
6070
}
6171
}
6272

73+
@Test // #2263
74+
public void shouldSortResultsBySortOptions() {
75+
76+
List<IndexQuery> indexQueries = new ArrayList<>();
77+
78+
indexQueries.add(buildIndex(SampleEntity.builder().id("1").message("ab xz").build()));
79+
indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build()));
80+
indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac xz hi").build()));
81+
82+
operations.bulkIndex(indexQueries, IndexCoordinates.of(indexNameProvider.indexName()));
83+
84+
NativeQuery query = NativeQuery.builder()
85+
.withSort(b -> b.field(fb -> fb.field("message").order(SortOrder.Asc))).build();
86+
87+
SearchHits<SampleEntity> searchHits = operations.search(query, SampleEntity.class,
88+
IndexCoordinates.of(indexNameProvider.indexName()));
89+
90+
assertThat(searchHits.getSearchHits()) //
91+
.satisfiesExactly(e -> {
92+
assertThat(e.getId()).isEqualTo("1");
93+
}, e -> {
94+
assertThat(e.getId()).isEqualTo("3");
95+
}, e -> {
96+
assertThat(e.getId()).isEqualTo("2");
97+
});
98+
}
99+
63100
@Override
64101
public boolean newElasticsearchClient() {
65102
return true;

0 commit comments

Comments
 (0)