Skip to content

Commit e8e407f

Browse files
tedliangxhaggi
authored andcommitted
DATAES-312 - Fix NullHandling.NULLS_LAST in query.sort
Original pull request: spring-projects#163
1 parent 1b0006f commit e8e407f

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@
6666
import org.elasticsearch.search.SearchHit;
6767
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
6868
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
69+
import org.elasticsearch.search.sort.FieldSortBuilder;
6970
import org.elasticsearch.search.sort.SortBuilder;
71+
import org.elasticsearch.search.sort.SortBuilders;
7072
import org.elasticsearch.search.sort.SortOrder;
7173
import org.elasticsearch.search.suggest.SuggestBuilder;
7274
import org.slf4j.Logger;
@@ -111,6 +113,7 @@
111113
* @author Ilkang Na
112114
* @author Alen Turkovic
113115
* @author Sascha Woo
116+
* @author Ted Liang
114117
*/
115118
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
116119

@@ -1011,8 +1014,15 @@ private SearchRequestBuilder prepareSearch(Query query) {
10111014

10121015
if (query.getSort() != null) {
10131016
for (Sort.Order order : query.getSort()) {
1014-
searchRequestBuilder.addSort(order.getProperty(),
1015-
order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC : SortOrder.ASC);
1017+
FieldSortBuilder sort = SortBuilders.fieldSort(order.getProperty())
1018+
.order(order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC);
1019+
if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) {
1020+
sort.missing("_first");
1021+
}
1022+
else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) {
1023+
sort.missing("_last");
1024+
}
1025+
searchRequestBuilder.addSort(sort);
10161026
}
10171027
}
10181028

src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,106 @@ public void shouldSortResultsGivenMultipleSortCriteria() {
494494
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
495495
}
496496

497+
@Test // DATAES-312
498+
public void shouldSortResultsGivenNullFirstSortCriteria() {
499+
// given
500+
List<IndexQuery> indexQueries;
501+
502+
// first document
503+
String documentId = randomNumeric(5);
504+
SampleEntity sampleEntity1 = SampleEntity.builder()
505+
.id(documentId)
506+
.message("abc")
507+
.rate(15)
508+
.version(System.currentTimeMillis())
509+
.build();
510+
511+
// second document
512+
String documentId2 = randomNumeric(5);
513+
SampleEntity sampleEntity2 = SampleEntity.builder()
514+
.id(documentId2)
515+
.message("xyz")
516+
.rate(5)
517+
.version(System.currentTimeMillis())
518+
.build();
519+
520+
// third document
521+
String documentId3 = randomNumeric(5);
522+
SampleEntity sampleEntity3 = SampleEntity.builder()
523+
.id(documentId3)
524+
.rate(10)
525+
.version(System.currentTimeMillis())
526+
.build();
527+
528+
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
529+
530+
elasticsearchTemplate.bulkIndex(indexQueries);
531+
elasticsearchTemplate.refresh(SampleEntity.class);
532+
533+
SearchQuery searchQuery = new NativeSearchQueryBuilder()
534+
.withQuery(matchAllQuery())
535+
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsFirst())))
536+
.build();
537+
538+
// when
539+
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
540+
541+
// then
542+
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
543+
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity3.getRate()));
544+
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
545+
}
546+
547+
@Test // DATAES-312
548+
public void shouldSortResultsGivenNullLastSortCriteria() {
549+
// given
550+
List<IndexQuery> indexQueries;
551+
552+
// first document
553+
String documentId = randomNumeric(5);
554+
SampleEntity sampleEntity1 = SampleEntity.builder()
555+
.id(documentId)
556+
.message("abc")
557+
.rate(15)
558+
.version(System.currentTimeMillis())
559+
.build();
560+
561+
// second document
562+
String documentId2 = randomNumeric(5);
563+
SampleEntity sampleEntity2 = SampleEntity.builder()
564+
.id(documentId2)
565+
.message("xyz")
566+
.rate(5)
567+
.version(System.currentTimeMillis())
568+
.build();
569+
570+
// third document
571+
String documentId3 = randomNumeric(5);
572+
SampleEntity sampleEntity3 = SampleEntity.builder()
573+
.id(documentId3)
574+
.rate(10)
575+
.version(System.currentTimeMillis())
576+
.build();
577+
578+
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
579+
580+
elasticsearchTemplate.bulkIndex(indexQueries);
581+
elasticsearchTemplate.refresh(SampleEntity.class);
582+
583+
SearchQuery searchQuery = new NativeSearchQueryBuilder()
584+
.withQuery(matchAllQuery())
585+
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsLast())))
586+
.build();
587+
588+
// when
589+
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
590+
591+
// then
592+
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
593+
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity1.getRate()));
594+
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity2.getMessage()));
595+
}
596+
497597
@Test
498598
public void shouldExecuteStringQuery() {
499599
// given
@@ -2100,4 +2200,4 @@ class ResultAggregator {
21002200
this.lastName = lastName;
21012201
}
21022202
}
2103-
}
2203+
}

0 commit comments

Comments
 (0)