Skip to content

Commit 5a66569

Browse files
committed
Add searchAfter interfaces to NativeSearchQueryBuilder
- support searchAfter for nativeSearchQuery
1 parent bf08000 commit 5a66569

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

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

-1
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,4 @@ default boolean hasSuggest() {
9999
default Iterator<SearchHit<T>> iterator() {
100100
return getSearchHits().iterator();
101101
}
102-
103102
}

src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java

+12
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* @author Peter-Josef Meisch
5151
* @author Peer Mueller
5252
* @author vdisk
53+
* @author owen.qq
5354
*/
5455
public class NativeSearchQueryBuilder {
5556

@@ -80,6 +81,7 @@ public class NativeSearchQueryBuilder {
8081
@Nullable private Duration timeout;
8182
private final List<RescorerQuery> rescorerQueries = new ArrayList<>();
8283
@Nullable private SuggestBuilder suggestBuilder;
84+
@Nullable private List<Object> searchAfter;
8385

8486
public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
8587
this.queryBuilder = queryBuilder;
@@ -342,6 +344,11 @@ public NativeSearchQueryBuilder withSuggestBuilder(SuggestBuilder suggestBuilder
342344
return this;
343345
}
344346

347+
public NativeSearchQueryBuilder withSearchAfter(List<Object> searchAfter) {
348+
this.searchAfter = searchAfter;
349+
return this;
350+
}
351+
345352
public NativeSearchQuery build() {
346353

347354
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery( //
@@ -431,6 +438,11 @@ public NativeSearchQuery build() {
431438
if (suggestBuilder != null) {
432439
nativeSearchQuery.setSuggestBuilder(suggestBuilder);
433440
}
441+
442+
if (searchAfter != null) {
443+
nativeSearchQuery.setSearchAfter(searchAfter);
444+
}
445+
434446
return nativeSearchQuery;
435447
}
436448
}

src/test/java/org/springframework/data/elasticsearch/core/paginating/SearchAfterIntegrationTests.java

+40-1
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core.paginating;
1717

18-
import static org.assertj.core.api.Assertions.*;
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.fail;
1920

2021
import java.util.ArrayList;
2122
import java.util.List;
2223
import java.util.stream.Collectors;
2324
import java.util.stream.IntStream;
2425

26+
import org.elasticsearch.search.sort.SortBuilders;
27+
import org.elasticsearch.search.sort.SortOrder;
2528
import org.junit.jupiter.api.DisplayName;
2629
import org.junit.jupiter.api.Test;
2730
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +36,7 @@
3336
import org.springframework.data.elasticsearch.annotations.FieldType;
3437
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
3538
import org.springframework.data.elasticsearch.core.SearchHits;
39+
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
3640
import org.springframework.data.elasticsearch.core.query.Query;
3741
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
3842
import org.springframework.lang.Nullable;
@@ -79,6 +83,41 @@ void shouldReadPagesWithSearchAfter() {
7983
assertThat(foundEntities).containsExactlyElementsOf(entities);
8084
}
8185

86+
@Test // #2105
87+
@DisplayName("should read pages with search_after using native search query")
88+
void shouldReadPagesWithSearchAfterUsingNativeSearchQuery() {
89+
90+
List<Entity> entities = IntStream.rangeClosed(1, 10).mapToObj(i -> new Entity((long) i, "message " + i))
91+
.collect(Collectors.toList());
92+
operations.save(entities);
93+
94+
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
95+
96+
nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 3));
97+
nativeSearchQueryBuilder.withSorts(SortBuilders.fieldSort("id").order(SortOrder.ASC));
98+
99+
List<Object> searchAfter = null;
100+
List<Entity> foundEntities = new ArrayList<>();
101+
102+
int loop = 0;
103+
do {
104+
nativeSearchQueryBuilder.withSearchAfter(searchAfter);
105+
SearchHits<Entity> searchHits = operations.search(nativeSearchQueryBuilder.build(), Entity.class);
106+
107+
if (searchHits.getSearchHits().size() == 0) {
108+
break;
109+
}
110+
foundEntities.addAll(searchHits.stream().map(searchHit -> searchHit.getContent()).collect(Collectors.toList()));
111+
searchAfter = searchHits.getSearchHit((int) (searchHits.getSearchHits().size() - 1)).getSortValues();
112+
113+
if (++loop > 10) {
114+
fail("loop not terminating");
115+
}
116+
} while (true);
117+
118+
assertThat(foundEntities).containsExactlyElementsOf(entities);
119+
}
120+
82121
@Document(indexName = "test-search-after")
83122
private static class Entity {
84123
@Nullable

0 commit comments

Comments
 (0)