diff --git a/pom.xml b/pom.xml
index ded4d85d02..97ecdf60ad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.5.0-SNAPSHOT
+ 4.5.0-GH-4889-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 58c63dfc97..e35e85033a 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.5.0-SNAPSHOT
+ 4.5.0-GH-4889-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 37e68c6f78..470fb51ad2 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.5.0-SNAPSHOT
+ 4.5.0-GH-4889-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java
index cebdf4e408..dd2b78de59 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java
@@ -36,6 +36,7 @@
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
+import org.springframework.data.mongodb.repository.util.SliceUtils;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
@@ -87,7 +88,7 @@ public Object execute(Query query) {
int pageSize = pageable.getPageSize();
// Apply Pageable but tweak limit to peek into next page
- Query modifiedQuery = query.with(pageable).limit(pageSize + 1);
+ Query modifiedQuery = SliceUtils.limitResult(query, pageable).with(pageable.getSort());
List result = find.matching(modifiedQuery).all();
boolean hasNext = result.size() > pageSize;
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java
index 0da7b76596..ec845510ce 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java
@@ -27,6 +27,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.MongoOperations;
@@ -271,6 +272,14 @@ public Page page(Pageable pageable) {
return createQuery().fetchPage(pageable);
}
+ @Override
+ public Slice slice(Pageable pageable) {
+
+ Assert.notNull(pageable, "Pageable must not be null");
+
+ return createQuery().fetchSlice(pageable);
+ }
+
@Override
public Stream stream() {
return createQuery().stream();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java
index bb0284f915..9a1482823f 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java
@@ -24,11 +24,13 @@
import org.bson.Document;
import org.reactivestreams.Publisher;
+
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Window;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
@@ -239,6 +241,14 @@ public Mono> page(Pageable pageable) {
return createQuery().fetchPage(pageable);
}
+ @Override
+ public Mono> slice(Pageable pageable) {
+
+ Assert.notNull(pageable, "Pageable must not be null");
+
+ return createQuery().fetchSlice(pageable);
+ }
+
@Override
public Mono count() {
return createQuery().fetchCount();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java
index c23ca5a979..bd4b241837 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.mongodb.repository.support;
+import org.springframework.data.mongodb.repository.util.SliceUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -27,6 +28,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.ReactiveFindOperation;
@@ -109,6 +111,20 @@ Mono> fetchPage(Pageable pageable) {
return content.flatMap(it -> ReactivePageableExecutionUtils.getPage(it, pageable, fetchCount()));
}
+ /**
+ * Fetch all matching query results as Slice.
+ *
+ * @return {@link Mono} emitting the requested Slice.
+ * @since 4.5
+ */
+ Mono> fetchSlice(Pageable pageable) {
+
+ Mono> content = createQuery().map(it -> SliceUtils.limitResult(it, pageable).with(pageable.getSort()))
+ .flatMapMany(it -> find.matching(it).all()).collectList();
+
+ return content.map(it -> SliceUtils.sliceResult(it, pageable));
+ }
+
/**
* Fetch the one matching query result.
*
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java
index ce6dcdd3a4..2f4c30ee7a 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java
@@ -33,6 +33,7 @@
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.ExecutableFindOperation;
@@ -42,6 +43,7 @@
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
+import org.springframework.data.mongodb.repository.util.SliceUtils;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.Streamable;
@@ -136,8 +138,7 @@ public boolean existsById(ID id) {
Query query = getIdQuery(id);
getReadPreference().ifPresent(query::withReadPreference);
- return mongoOperations.exists(query, entityInformation.getJavaType(),
- entityInformation.getCollectionName());
+ return mongoOperations.exists(query, entityInformation.getJavaType(), entityInformation.getCollectionName());
}
@Override
@@ -455,6 +456,16 @@ public Page page(Pageable pageable) {
return PageableExecutionUtils.getPage(list, pageable, this::count);
}
+ @Override
+ public Slice slice(Pageable pageable) {
+
+ Assert.notNull(pageable, "Pageable must not be null");
+
+ List resultList = createQuery(q -> SliceUtils.limitResult(q, pageable).with(pageable.getSort())).all();
+
+ return SliceUtils.sliceResult(resultList, pageable);
+ }
+
@Override
public Stream stream() {
return createQuery().stream();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java
index e8ff60de46..1c1df2c9a1 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java
@@ -17,6 +17,7 @@
import static org.springframework.data.mongodb.core.query.Criteria.*;
+import org.springframework.data.mongodb.repository.util.SliceUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -37,6 +38,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -592,6 +594,13 @@ public Mono> page(Pageable pageable) {
return items.flatMap(content -> ReactivePageableExecutionUtils.getPage(content, pageable, this.count()));
}
+ @Override
+ public Mono> slice(Pageable pageable) {
+
+ return createQuery(q -> SliceUtils.limitResult(q, pageable).with(pageable.getSort())).all().collectList()
+ .map(it -> SliceUtils.sliceResult(it, pageable));
+ }
+
@Override
public Mono count() {
return createQuery().count();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java
index c8cad08c09..0ef6c38744 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java
@@ -22,16 +22,19 @@
import java.util.stream.Stream;
import org.bson.Document;
+
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.ExecutableFindOperation;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.FieldName;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.repository.util.SliceUtils;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.lang.Nullable;
@@ -182,6 +185,20 @@ public Page fetchPage(Pageable pageable) {
}
}
+ /**
+ * Fetch a {@link Slice}.
+ *
+ * @param pageable defines range and sort of requested slice
+ * @return new instance of {@link Slice} containing matching results within range.
+ * @since 4.5
+ */
+ public Slice fetchSlice(Pageable pageable) {
+
+ List content = find.matching(SliceUtils.limitResult(createQuery(), pageable).with(pageable.getSort())).all();
+
+ return SliceUtils.sliceResult(content, pageable);
+ }
+
@Override
public T fetchFirst() {
try {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java
new file mode 100644
index 0000000000..db22c3fea4
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/util/SliceUtils.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.repository.util;
+
+import java.util.List;
+
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Slice;
+import org.springframework.data.domain.SliceImpl;
+import org.springframework.data.mongodb.core.query.Query;
+
+/**
+ * Utility methods for {@link Slice} handling.
+ *
+ * @author Mark Paluch
+ * @since 4.5
+ */
+public class SliceUtils {
+
+ /**
+ * Creates a {@link Slice} given {@link Pageable} and {@link List} of results.
+ *
+ * @param
+ * @param resultList
+ * @param pageable
+ * @return
+ */
+ public static Slice sliceResult(List resultList, Pageable pageable) {
+
+ boolean hasNext = resultList.size() > pageable.getPageSize();
+
+ if (hasNext) {
+ resultList = resultList.subList(0, pageable.getPageSize());
+ }
+
+ return new SliceImpl<>(resultList, pageable, hasNext);
+ }
+
+ /**
+ * Customize query for slice retrieval.
+ *
+ * @param query the source query
+ * @param pageable paging to apply.
+ * @return new instance of {@link Query} if either {@link Pageable#isPaged() paged} or {@link Pageable#getSort()
+ * sorted}, the source query otherwise.
+ */
+ public static Query limitResult(Query query, Pageable pageable) {
+
+ if (pageable.isUnpaged()) {
+ return query;
+ }
+
+ Query target = Query.of(query);
+ target.skip(pageable.getOffset());
+ target.limit(pageable.getPageSize() + 1);
+
+ return target;
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java
index 8ab45e5964..44235c54ef 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java
@@ -607,6 +607,33 @@ void findByShouldApplyPagination() {
}).verifyComplete();
}
+ @Test // GH-4889
+ void findByShouldApplySlice() {
+
+ ReactivePerson probe = new ReactivePerson();
+ probe.setLastname(oliver.getLastname());
+
+ repository
+ .findBy(Example.of(probe, matching().withIgnorePaths("age")),
+ it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))) //
+ .as(StepVerifier::create) //
+ .assertNext(it -> {
+
+ assertThat(it.hasNext()).isTrue();
+ assertThat(it.getContent()).contains(dave);
+ }).verifyComplete();
+
+ repository
+ .findBy(Example.of(probe, matching().withIgnorePaths("age")),
+ it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))) //
+ .as(StepVerifier::create) //
+ .assertNext(it -> {
+
+ assertThat(it.hasNext()).isFalse();
+ assertThat(it.getContent()).contains(oliver);
+ }).verifyComplete();
+ }
+
@Test // GH-3757
void findByShouldCount() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java
index 18d86d02dc..7d9024e2fb 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java
@@ -31,6 +31,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.MongoDatabaseFactory;
@@ -314,6 +315,7 @@ public void findByShouldApplyPagination() {
Page first = repository.findBy(person.lastname.eq(oliver.getLastname()),
it -> it.page(PageRequest.of(0, 1, Sort.by("firstname"))));
+
assertThat(first.getTotalElements()).isEqualTo(2);
assertThat(first.getContent()).contains(dave);
@@ -324,6 +326,22 @@ public void findByShouldApplyPagination() {
assertThat(next.getContent()).contains(oliver);
}
+ @Test // GH-4889
+ public void findByShouldApplySlice() {
+
+ Slice first = repository.findBy(person.lastname.eq(oliver.getLastname()),
+ it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname"))));
+
+ assertThat(first.hasNext()).isTrue();
+ assertThat(first.getContent()).contains(dave);
+
+ Slice next = repository.findBy(person.lastname.eq(oliver.getLastname()),
+ it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname"))));
+
+ assertThat(next.hasNext()).isFalse();
+ assertThat(next.getContent()).contains(oliver);
+ }
+
@Test // GH-3757
public void findByShouldCount() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java
index 7e6f6e4995..807b7aec22 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java
@@ -31,6 +31,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
@@ -50,8 +51,8 @@
import org.springframework.data.mongodb.repository.User;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.test.util.MongoTestUtils;
-import org.springframework.data.repository.query.FluentQuery;
import org.springframework.data.mongodb.test.util.ReactiveMongoClientClosingTestConfiguration;
+import org.springframework.data.repository.query.FluentQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@@ -414,6 +415,28 @@ public void findByShouldApplyPagination() {
}).verifyComplete();
}
+ @Test // GH-4889
+ public void findByShouldApplySlice() {
+
+ repository
+ .findBy(person.lastname.eq(oliver.getLastname()), it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname")))) //
+ .as(StepVerifier::create) //
+ .assertNext(it -> {
+
+ assertThat(it.hasNext()).isTrue();
+ assertThat(it.getContent()).containsOnly(dave);
+ }).verifyComplete();
+
+ repository
+ .findBy(person.lastname.eq(oliver.getLastname()), it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname")))) //
+ .as(StepVerifier::create) //
+ .assertNext(it -> {
+
+ assertThat(it.hasNext()).isFalse();
+ assertThat(it.getContent()).containsOnly(oliver);
+ }).verifyComplete();
+ }
+
@Test // GH-3757
public void findByShouldCount() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java
index 98cbab868b..60c02ee775 100755
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java
@@ -38,6 +38,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.MongoTransactionManager;
@@ -579,6 +580,24 @@ void findByShouldApplyPagination() {
assertThat(next.getContent()).contains(oliver);
}
+ @Test // GH-4889
+ void findByShouldApplySlice() {
+
+ Person probe = new Person();
+ probe.setLastname(oliver.getLastname());
+
+ Slice first = repository.findBy(Example.of(probe, getMatcher()),
+ it -> it.slice(PageRequest.of(0, 1, Sort.by("firstname"))));
+ assertThat(first.hasNext()).isTrue();
+ assertThat(first.getContent()).contains(dave);
+
+ Slice next = repository.findBy(Example.of(probe, getMatcher()),
+ it -> it.slice(PageRequest.of(1, 1, Sort.by("firstname"))));
+
+ assertThat(next.hasNext()).isFalse();
+ assertThat(next.getContent()).contains(oliver);
+ }
+
@Test // GH-3757
void findByShouldCount() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java
new file mode 100644
index 0000000000..eb1353cde3
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/util/SliceUtilsUnitTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.repository.util;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import java.util.stream.Stream;
+
+import org.bson.Document;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.mongodb.core.query.BasicQuery;
+import org.springframework.data.mongodb.core.query.Query;
+
+/**
+ * @author Christoph Strobl
+ */
+class SliceUtilsUnitTests {
+
+ @ParameterizedTest
+ @MethodSource("paged")
+ void pagedPageableModifiesQuery(Pageable page) {
+
+ Query source = new BasicQuery(Document.parse("{ 'spring' : 'data' }"));
+
+ Query target = SliceUtils.limitResult(source, page);
+ assertThat(target.getQueryObject()).isEqualTo(source.getQueryObject());
+ assertThat(target).isNotSameAs(source);
+ assertThat(target.isLimited()).isTrue();
+ assertThat(target.getSkip()).isEqualTo(page.getOffset());
+ assertThat(target.getLimit()).isEqualTo(page.toLimit().max() + 1);
+ assertThat(target.getSortObject()).isEqualTo(source.getSortObject());
+ }
+
+ @ParameterizedTest
+ @MethodSource("unpaged")
+ void unpagedPageableDoesNotModifyQuery(Pageable page) {
+
+ Query source = spy(new BasicQuery(Document.parse("{ 'spring' : 'data' }")));
+
+ Query target = SliceUtils.limitResult(source, page);
+
+ verifyNoInteractions(source);
+
+ assertThat(target).isSameAs(source);
+ assertThat(target.isLimited()).isFalse();
+ }
+
+ public static Stream paged() {
+ return Stream.of(Arguments.of(Pageable.ofSize(1)), Arguments.of(PageRequest.of(0, 10)),
+ Arguments.of(PageRequest.of(0, 10, Direction.ASC, "name")));
+ }
+
+ public static Stream unpaged() {
+ return Stream.of(Arguments.of(Pageable.unpaged()), Arguments.of(Pageable.unpaged(Sort.by("name"))));
+ }
+}