From 37bc97d5eb7186df881c61a4c1ed96a0b2b3c9f6 Mon Sep 17 00:00:00 2001 From: xhaggi Date: Thu, 14 Jun 2018 16:27:17 +0200 Subject: [PATCH] DATAES-467 - Fix sorting by _score if Spring Data sort is used. Original pull request: #209. --- .../core/ElasticsearchTemplate.java | 31 ++++++++++++++----- .../core/ElasticsearchTemplateTests.java | 23 ++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 2b3936840..be0242391 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -67,6 +67,7 @@ import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.ScoreSortBuilder; import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; @@ -131,6 +132,8 @@ import org.springframework.util.StringUtils; public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware { private static final Logger logger = LoggerFactory.getLogger(ElasticsearchTemplate.class); + private static final String FIELD_SCORE = "_score"; + private Client client; private ElasticsearchConverter elasticsearchConverter; private ResultsMapper resultsMapper; @@ -1022,15 +1025,27 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati if (query.getSort() != null) { for (Sort.Order order : query.getSort()) { - FieldSortBuilder sort = SortBuilders.fieldSort(order.getProperty()) - .order(order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC); - if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) { - sort.missing("_first"); + SortOrder sortOrder = order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC; + + if (FIELD_SCORE.equals(order.getProperty())) { + ScoreSortBuilder sort = SortBuilders // + .scoreSort() // + .order(sortOrder); + + searchRequestBuilder.addSort(sort); + } else { + FieldSortBuilder sort = SortBuilders // + .fieldSort(order.getProperty()) // + .order(sortOrder); + + if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) { + sort.missing("_first"); + } else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) { + sort.missing("_last"); + } + + searchRequestBuilder.addSort(sort); } - else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) { - sort.missing("_last"); - } - searchRequestBuilder.addSort(sort); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index 33cba185d..dbb3d8d28 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -564,6 +564,29 @@ public class ElasticsearchTemplateTests { assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity2.getMessage())); } + @Test // DATAES-467 + public void shouldSortResultsByScore() { + // given + List entities = Arrays.asList( // + SampleEntity.builder().id("1").message("abc").build(), // + SampleEntity.builder().id("2").message("def").build(), // + SampleEntity.builder().id("3").message("ghi").build()); + + elasticsearchTemplate.bulkIndex(getIndexQueries(entities)); + elasticsearchTemplate.refresh(SampleEntity.class); + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(matchAllQuery()) + .withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("_score")))) + .build(); + + // when + Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + + // then + assertThat(sampleEntities.getTotalElements(), equalTo(3L)); + } + @Test public void shouldExecuteStringQuery() { // given