[elc] add support for sorting results by SortOptions to NativeQuery.

Original Pull Request #2264
Closes #2263
This commit is contained in:
Sascha Woo 2022-08-10 21:34:17 +02:00 committed by GitHub
parent c4910bf399
commit 6cfb8eeea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 5 deletions

View File

@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
@ -26,7 +27,6 @@ import java.util.List;
import java.util.Map;
import org.springframework.data.elasticsearch.core.query.BaseQuery;
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
import org.springframework.data.elasticsearch.core.query.ScriptedField;
import org.springframework.lang.Nullable;
@ -35,6 +35,7 @@ import org.springframework.lang.Nullable;
* Elasticsearch Client library.
*
* @author Peter-Josef Meisch
* @author Sascha Woo
* @since 4.4
*/
public class NativeQuery extends BaseQuery {
@ -46,6 +47,7 @@ public class NativeQuery extends BaseQuery {
@Nullable private Suggester suggester;
@Nullable private FieldCollapse fieldCollapse;
private List<ScriptedField> scriptedFields = Collections.emptyList();
private List<SortOptions> sortOptions = Collections.emptyList();
public NativeQuery(NativeQueryBuilder builder) {
super(builder);
@ -55,6 +57,7 @@ public class NativeQuery extends BaseQuery {
this.suggester = builder.getSuggester();
this.fieldCollapse = builder.getFieldCollapse();
this.scriptedFields = builder.getScriptedFields();
this.sortOptions = builder.getSortOptions();
}
public NativeQuery(@Nullable Query query) {
@ -92,4 +95,8 @@ public class NativeQuery extends BaseQuery {
public List<ScriptedField> getScriptedFields() {
return scriptedFields;
}
public List<SortOptions> getSortOptions() {
return sortOptions;
}
}

View File

@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
@ -22,19 +23,21 @@ import co.elastic.clients.elasticsearch.core.search.Suggester;
import co.elastic.clients.util.ObjectBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
import org.springframework.data.elasticsearch.core.query.ScriptedField;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* @author Peter-Josef Meisch
* @author Sascha Woo
* @since 4.4
*/
public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQueryBuilder> {
@ -45,7 +48,10 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
@Nullable private Suggester suggester;
@Nullable private FieldCollapse fieldCollapse;
private final List<ScriptedField> scriptedFields = new ArrayList<>();
public NativeQueryBuilder() {}
private List<SortOptions> sortOptions = new ArrayList<>();
public NativeQueryBuilder() {
}
@Nullable
public Query getQuery() {
@ -75,6 +81,10 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
return scriptedFields;
}
public List<SortOptions> getSortOptions() {
return sortOptions;
}
public NativeQueryBuilder withQuery(Query query) {
Assert.notNull(query, "query must not be null");
@ -129,6 +139,34 @@ public class NativeQueryBuilder extends BaseQueryBuilder<NativeQuery, NativeQuer
return this;
}
public NativeQueryBuilder withSort(List<SortOptions> values) {
Assert.notEmpty(values, "values must not be empty");
sortOptions.clear();
sortOptions.addAll(values);
return this;
}
public NativeQueryBuilder withSort(SortOptions value, SortOptions... values) {
Assert.notNull(value, "value must not be null");
sortOptions.add(value);
if (values.length > 0) {
sortOptions.addAll(Arrays.asList(values));
}
return this;
}
public NativeQueryBuilder withSort(Function<SortOptions.Builder, ObjectBuilder<SortOptions>> fn) {
Assert.notNull(fn, "fn must not be null");
withSort(fn.apply(new SortOptions.Builder()).build());
return this;
}
public NativeQuery build() {
return new NativeQuery(this);
}

View File

@ -101,6 +101,7 @@ import org.springframework.util.StringUtils;
* Class to create Elasticsearch request and request builders.
*
* @author Peter-Josef Meisch
* @author Sascha Woo
* @since 4.4
*/
class RequestConverter {
@ -1405,7 +1406,7 @@ class RequestConverter {
builder //
.suggest(query.getSuggester()) //
.collapse(query.getFieldCollapse()) //
;
.sort(query.getSortOptions());
if (!isEmpty(query.getAggregations())) {
builder.aggregations(query.getAggregations());
@ -1424,7 +1425,7 @@ class RequestConverter {
builder //
.suggest(query.getSuggester()) //
.collapse(query.getFieldCollapse()) //
;
.sort(query.getSortOptions());
if (!isEmpty(query.getAggregations())) {
builder.aggregations(query.getAggregations());

View File

@ -15,25 +15,34 @@
*/
package org.springframework.data.elasticsearch.core;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.elasticsearch.client.elc.QueryBuilders.*;
import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
import co.elastic.clients.elasticsearch._types.SortOptionsBuilders;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.FunctionBoostMode;
import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScoreMode;
import co.elastic.clients.elasticsearch.core.search.FieldCollapse;
import co.elastic.clients.json.JsonData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.BaseQueryBuilder;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.RescorerQuery;
import org.springframework.data.elasticsearch.core.query.ScriptData;
@ -45,6 +54,7 @@ import org.springframework.test.context.ContextConfiguration;
/**
* @author Farid Faoudi
* @author Sascha Woo
* @since 4.4
*/
@ContextConfiguration(classes = { ElasticsearchELCIntegrationTests.Config.class })
@ -60,6 +70,33 @@ public class ElasticsearchELCIntegrationTests extends ElasticsearchIntegrationTe
}
}
@Test // #2263
public void shouldSortResultsBySortOptions() {
List<IndexQuery> indexQueries = new ArrayList<>();
indexQueries.add(buildIndex(SampleEntity.builder().id("1").message("ab xz").build()));
indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build()));
indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac xz hi").build()));
operations.bulkIndex(indexQueries, IndexCoordinates.of(indexNameProvider.indexName()));
NativeQuery query = NativeQuery.builder()
.withSort(b -> b.field(fb -> fb.field("message").order(SortOrder.Asc))).build();
SearchHits<SampleEntity> searchHits = operations.search(query, SampleEntity.class,
IndexCoordinates.of(indexNameProvider.indexName()));
assertThat(searchHits.getSearchHits()) //
.satisfiesExactly(e -> {
assertThat(e.getId()).isEqualTo("1");
}, e -> {
assertThat(e.getId()).isEqualTo("3");
}, e -> {
assertThat(e.getId()).isEqualTo("2");
});
}
@Override
public boolean newElasticsearchClient() {
return true;