diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScrollUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScrollUtils.java index ecd7aaf81..db910e7fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScrollUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScrollUtils.java @@ -63,18 +63,18 @@ class ScrollUtils { KeysetScrollPosition keyset = query.getKeyset(); KeysetScrollDirector director = KeysetScrollDirector.of(keyset.getDirection()); - director.postPostProcessResults(result); + List resultsToUse = director.postPostProcessResults(result, query.getLimit()); IntFunction positionFunction = value -> { - T last = result.get(value); + T last = resultsToUse.get(value); Entity entity = operations.forEntity(last); Map keys = entity.extractKeys(sortObject, sourceType); return KeysetScrollPosition.of(keys); }; - return createWindow(result, query.getLimit(), positionFunction); + return Window.from(resultsToUse, positionFunction, hasMoreElements(result, query.getLimit())); } static Window createWindow(List result, int limit, IntFunction positionFunction) { @@ -187,13 +187,14 @@ class ScrollUtils { return queryObject; } - public void postPostProcessResults(List result) { - - } - protected String getComparator(int sortOrder) { return sortOrder == 1 ? "$gt" : "$lt"; } + + protected List postPostProcessResults(List list, int limit) { + return getFirst(limit, list); + } + } /** @@ -219,20 +220,48 @@ class ScrollUtils { } @Override - protected String getComparator(int sortOrder) { + public List postPostProcessResults(List list, int limit) { - // use gte/lte to include the object at the cursor/keyset so that - // we can include it in the result to check whether there is a next object. - // It needs to be filtered out later on. - return sortOrder == 1 ? "$gte" : "$lte"; - } - - @Override - public void postPostProcessResults(List result) { // flip direction of the result list as we need to accomodate for the flipped sort order for proper offset // querying. - Collections.reverse(result); + Collections.reverse(list); + + return getLast(limit, list); } + } + /** + * Return the first {@code count} items from the list. + * + * @param count + * @param list + * @return + * @param + */ + static List getFirst(int count, List list) { + + if (count > 0 && list.size() > count) { + return list.subList(0, count); + } + + return list; + } + + /** + * Return the last {@code count} items from the list. + * + * @param count + * @param list + * @return + * @param + */ + static List getLast(int count, List list) { + + if (count > 0 && list.size() > count) { + return list.subList(list.size() - (count), list.size()); + } + + return list; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateScrollTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateScrollTests.java index 87e75864b..8374f6ab4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateScrollTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateScrollTests.java @@ -184,11 +184,18 @@ class MongoTemplateScrollTests { assertThat(window.isLast()).isTrue(); assertThat(window).hasSize(6); - KeysetScrollPosition scrollPosition = (KeysetScrollPosition) window.positionAt(window.size() - 1); + KeysetScrollPosition scrollPosition = (KeysetScrollPosition) window.positionAt(window.size() - 2); KeysetScrollPosition reversePosition = KeysetScrollPosition.of(scrollPosition.getKeys(), Direction.Backward); window = template.scroll(q.with(reversePosition).limit(2), Person.class); + assertThat(window).hasSize(2); + assertThat(window).containsOnly(jane_42, john20); + assertThat(window.hasNext()).isTrue(); + assertThat(window.isLast()).isFalse(); + + window = template.scroll(q.with(window.positionAt(0)).limit(2), Person.class); + assertThat(window).hasSize(2); assertThat(window).containsOnly(john20, john40_1); assertThat(window.hasNext()).isTrue();