Browse Source

DATAMONGO-1464 - Optimize query execution for pagination queries.

We execute paged queries now in an optimized way. The data is obtained for each paged execution but the count query is deferred. We determine the total from the pageable and the results in which we don't hit the page size bounds (i.e. results are less than a full page without offset or results are greater 0 and less than a full page with offset). In all other cases we issue an additional count query.

Original pull request: #379.
pull/382/head
Mark Paluch 10 years ago committed by Oliver Gierke
parent
commit
353b836a77
  1. 63
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java
  2. 28
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java
  3. 20
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java
  4. 12
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
  5. 5
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java
  6. 182
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java
  7. 23
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java

63
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java

@ -18,13 +18,12 @@ package org.springframework.data.mongodb.repository.query; @@ -18,13 +18,12 @@ package org.springframework.data.mongodb.repository.query;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Range;
import org.springframework.data.domain.Slice;
@ -39,6 +38,8 @@ import org.springframework.data.mongodb.core.query.NearQuery; @@ -39,6 +38,8 @@ import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.data.repository.support.PageableExecutionUtils.TotalSupplier;
import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation;
@ -108,6 +109,7 @@ interface MongoQueryExecution { @@ -108,6 +109,7 @@ interface MongoQueryExecution {
* {@link MongoQueryExecution} for pagination queries.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@RequiredArgsConstructor
static final class PagedExecution implements MongoQueryExecution {
@ -120,29 +122,27 @@ interface MongoQueryExecution { @@ -120,29 +122,27 @@ interface MongoQueryExecution {
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public Object execute(Query query, Class<?> type, String collection) {
int overallLimit = query.getLimit();
long count = operations.count(query, type, collection);
count = overallLimit != 0 ? Math.min(count, query.getLimit()) : count;
public Object execute(final Query query, final Class<?> type, final String collection) {
boolean pageableOutOfScope = pageable.getOffset() > count;
if (pageableOutOfScope) {
return new PageImpl<Object>(Collections.emptyList(), pageable, count);
}
final int overallLimit = query.getLimit();
// Apply raw pagination
query = query.with(pageable);
query.with(pageable);
// Adjust limit if page would exceed the overall limit
if (overallLimit != 0 && pageable.getOffset() + pageable.getPageSize() > overallLimit) {
query.limit(overallLimit - pageable.getOffset());
}
List<?> result = operations.find(query, type, collection);
return new PageImpl(result, pageable, count);
return PageableExecutionUtils.getPage(operations.find(query, type, collection), pageable, new TotalSupplier() {
@Override
public long get() {
long count = operations.count(query, type, collection);
return overallLimit != 0 ? Math.min(count, overallLimit) : count;
}
});
}
}
@ -233,6 +233,12 @@ interface MongoQueryExecution { @@ -233,6 +233,12 @@ interface MongoQueryExecution {
}
}
/**
* {@link MongoQueryExecution} to execute geo-near queries with paging.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
static final class PagingGeoNearExecution extends GeoNearExecution {
private final MongoOperations operations;
@ -257,14 +263,27 @@ interface MongoQueryExecution { @@ -257,14 +263,27 @@ interface MongoQueryExecution {
* @return
*/
@Override
public Object execute(Query query, Class<?> type, String collection) {
public Object execute(Query query, Class<?> type, final String collection) {
GeoResults<Object> geoResults = doExecuteQuery(query, type, collection);
ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(),
accessor);
Query countQuery = mongoQuery.applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor));
long count = operations.count(countQuery, collection);
Page<GeoResult<Object>> page = PageableExecutionUtils.getPage(geoResults.getContent(), accessor.getPageable(),
new TotalSupplier() {
@Override
public long get() {
ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(),
accessor);
Query countQuery = mongoQuery
.applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor));
return operations.count(countQuery, collection);
}
});
return new GeoPage<Object>(doExecuteQuery(query, type, collection), accessor.getPageable(), count);
// transform to GeoPage after applying optimization
return new GeoPage<Object>(geoResults, accessor.getPageable(), page.getTotalElements());
}
}

28
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@ -19,7 +19,6 @@ import java.io.Serializable; @@ -19,7 +19,6 @@ import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
@ -32,6 +31,8 @@ import org.springframework.data.querydsl.QueryDslPredicateExecutor; @@ -32,6 +31,8 @@ import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.EntityMetadata;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.data.repository.support.PageableExecutionUtils.TotalSupplier;
import org.springframework.util.Assert;
import com.querydsl.core.types.EntityPath;
@ -46,6 +47,7 @@ import com.querydsl.mongodb.AbstractMongodbQuery; @@ -46,6 +47,7 @@ import com.querydsl.mongodb.AbstractMongodbQuery;
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Mark Paluch
*/
public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID>
implements QueryDslPredicateExecutor<T> {
@ -136,13 +138,17 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM @@ -136,13 +138,17 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Pageable)
*/
@Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
public Page<T> findAll(final Predicate predicate, Pageable pageable) {
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> countQuery = createQueryFor(predicate);
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQueryFor(predicate);
return new PageImpl<T>(applyPagination(query, pageable).fetchResults().getResults(), pageable,
countQuery.fetchCount());
return PageableExecutionUtils.getPage(applyPagination(query, pageable).fetchResults().getResults(), pageable, new TotalSupplier() {
@Override
public long get() {
return createQueryFor(predicate).fetchCount();
}
});
}
/*
@ -152,11 +158,15 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM @@ -152,11 +158,15 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
@Override
public Page<T> findAll(Pageable pageable) {
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> countQuery = createQuery();
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQuery();
return new PageImpl<T>(applyPagination(query, pageable).fetchResults().getResults(), pageable,
countQuery.fetchCount());
return PageableExecutionUtils.getPage(applyPagination(query, pageable).fetchResults().getResults(), pageable, new TotalSupplier() {
@Override
public long get() {
return createQuery().fetchCount();
}
});
}
/*

20
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java

@ -36,6 +36,8 @@ import org.springframework.data.mongodb.core.query.Criteria; @@ -36,6 +36,8 @@ import org.springframework.data.mongodb.core.query.Criteria;
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.repository.support.PageableExecutionUtils;
import org.springframework.data.repository.support.PageableExecutionUtils.TotalSupplier;
import org.springframework.util.Assert;
/**
@ -266,20 +268,20 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR @@ -266,20 +268,20 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
* @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example, org.springframework.data.domain.Pageable)
*/
@Override
public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
public <S extends T> Page<S> findAll(final Example<S> example, Pageable pageable) {
Assert.notNull(example, "Sample must not be null!");
Query q = new Query(new Criteria().alike(example)).with(pageable);
final Query q = new Query(new Criteria().alike(example)).with(pageable);
long count = mongoOperations.count(q, example.getProbeType(), entityInformation.getCollectionName());
List<S> list = mongoOperations.find(q, example.getProbeType(), entityInformation.getCollectionName());
return PageableExecutionUtils.getPage(list, pageable, new TotalSupplier() {
if (count == 0) {
return new PageImpl<S>(Collections.<S> emptyList());
}
return new PageImpl<S>(mongoOperations.find(q, example.getProbeType(), entityInformation.getCollectionName()),
pageable, count);
@Override
public long get() {
return mongoOperations.count(q, example.getProbeType(), entityInformation.getCollectionName());
}
});
}
/*

12
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java

@ -321,6 +321,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -321,6 +321,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(page.isFirst(), is(true));
assertThat(page.isLast(), is(false));
assertThat(page.getNumberOfElements(), is(2));
assertThat(page.getTotalElements(), is(4L));
assertThat(page, hasItems(carter, stefan));
}
@ -947,7 +948,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -947,7 +948,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
}
/**
* @see DATAMONGO-950
* @see DATAMONGO-950, DATAMONGO-1464
*/
@Test
public void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() {
@ -956,6 +957,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -956,6 +957,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(0, 2));
assertThat(result.getContent().size(), is(2));
assertThat(result.getTotalElements(), is(3L));
}
/**
@ -971,19 +973,20 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -971,19 +973,20 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
}
/**
* @see DATAMONGO-950
* @see DATAMONGO-950, DATAMONGO-1464
*/
@Test
public void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() {
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(2, 2));
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(100, 2));
assertThat(result.getContent().size(), is(0));
assertThat(result.getTotalElements(), is(3L));
}
/**
* @see DATAMONGO-996, DATAMONGO-950
* @see DATAMONGO-996, DATAMONGO-950, DATAMONGO-1464
*/
@Test
public void gettingNonFirstPageWorksWithoutLimitBeingSet() {
@ -993,6 +996,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -993,6 +996,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(slice.getContent(), hasSize(1));
assertThat(slice.hasPrevious(), is(true));
assertThat(slice.hasNext(), is(false));
assertThat(slice.getTotalElements(), is(2L));
}
/**

5
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014-2015 the original author or authors.
* Copyright 2014-2016 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.
@ -67,6 +67,7 @@ import com.mongodb.WriteResult; @@ -67,6 +67,7 @@ import com.mongodb.WriteResult;
* @author Christoph Strobl
* @author Oliver Gierke
* @author Thomas Darimont
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class AbstractMongoQueryUnitTests {
@ -188,7 +189,7 @@ public class AbstractMongoQueryUnitTests { @@ -188,7 +189,7 @@ public class AbstractMongoQueryUnitTests {
public void metadataShouldBeAddedToCountQueryCorrectly() {
MongoQueryFake query = createQueryForMethod("findByFirstname", String.class, Pageable.class);
query.execute(new Object[] { "fake", new PageRequest(0, 10) });
query.execute(new Object[] { "fake", new PageRequest(1, 10) });
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);

182
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java

@ -0,0 +1,182 @@ @@ -0,0 +1,182 @@
/*
* Copyright 2016 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
*
* http://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.query;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoPage;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagingGeoNearExecution;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.util.ReflectionUtils;
/**
* Unit tests for {@link MongoQueryExecution}.
*
* @author Mark Paluch
* @soundtrack U Can't Touch This - MC Hammer
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unchecked")
public class MongoQueryExecutionUnitTests {
@Mock MongoOperations mongoOperationsMock;
@Mock DbRefResolver dbRefResolver;
Point POINT = new Point(10, 20);
Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS);
RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class);
MongoMappingContext context = new MongoMappingContext();
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
Method method = ReflectionUtils.findMethod(PersonRepository.class, "findByLocationNear", Point.class, Distance.class,
Pageable.class);
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
@Before
public void setUp() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
when(mongoOperationsMock.getConverter()).thenReturn(converter);
}
/**
* @see DATAMONGO-1464
*/
@Test
public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person")))
.thenReturn(Collections.<Person> emptyList());
PagedExecution execution = new PagedExecution(mongoOperationsMock, new PageRequest(0, 10));
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock, never()).count(any(Query.class), eq(Person.class), eq("person"));
}
/**
* @see DATAMONGO-1464
*/
@Test
public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person")))
.thenReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person()));
PagedExecution execution = new PagedExecution(mongoOperationsMock, new PageRequest(0, 10));
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock, never()).count(any(Query.class), eq(Person.class), eq("person"));
}
/**
* @see DATAMONGO-1464
*/
@Test
public void pagedExecutionRetrievesObjectsForPageableOutOfRange() throws Exception {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person")))
.thenReturn(Collections.<Person> emptyList());
PagedExecution execution = new PagedExecution(mongoOperationsMock, new PageRequest(2, 10));
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock).count(any(Query.class), eq(Person.class), eq("person"));
}
/**
* @see DATAMONGO-1464
*/
@Test
public void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() throws Exception {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
new Object[] { POINT, DISTANCE, new PageRequest(0, 10) });
PartTreeMongoQuery query = new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
GeoResult<Person> result = new GeoResult<Person>(new Person(), DISTANCE);
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Arrays.asList(result, result, result, result)));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, accessor,
ClassTypeInformation.fromReturnTypeOf(method), query);
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock, never()).count(any(Query.class), eq("person"));
}
/**
* @see DATAMONGO-1464
*/
@Test
public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() throws Exception {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
new Object[] { POINT, DISTANCE, new PageRequest(2, 10) });
PartTreeMongoQuery query = new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Collections.<GeoResult<Person>> emptyList()));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, accessor,
ClassTypeInformation.fromReturnTypeOf(method), query);
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock).count(any(Query.class), eq("person"));
}
interface PersonRepository extends Repository<Person, Long> {
GeoPage<Person> findByLocationNear(Point point, Distance distance, Pageable pageable);
}
}

23
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java

@ -33,17 +33,17 @@ import org.junit.Test; @@ -33,17 +33,17 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.ExampleMatcher.*;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.repository.Address;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.data.mongodb.repository.User;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -174,7 +174,7 @@ public class SimpleMongoRepositoryTests { @@ -174,7 +174,7 @@ public class SimpleMongoRepositoryTests {
}
/**
* @see DATAMONGO-1245
* @see DATAMONGO-1245, DATAMONGO-1464
*/
@Test
public void findByExampleShouldLookUpEntriesCorrectly() {
@ -187,6 +187,23 @@ public class SimpleMongoRepositoryTests { @@ -187,6 +187,23 @@ public class SimpleMongoRepositoryTests {
assertThat(result.getContent(), hasItems(dave, oliver));
assertThat(result.getContent(), hasSize(2));
assertThat(result.getTotalPages(), is(1));
}
/**
* @see DATAMONGO-1464
*/
@Test
public void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
Page<Person> result = repository.findAll(Example.of(sample), new PageRequest(0, 1));
assertThat(result.getContent(), hasSize(1));
assertThat(result.getTotalPages(), is(2));
}
/**

Loading…
Cancel
Save