DATAMONGO-870 - Added support for sliced query execution.

Added support for Slice as return type for query methods. The execution will expand the requested page size by one to read one more element than actually requested. If that additional element is returned, it will considered to be an indicator for whether a next slice is available.

Related issues: DATACMNS-397.
This commit is contained in:
Oliver Gierke
2014-03-04 17:27:31 +01:00
parent 8dd08a36a0
commit 6963f9e07a
3 changed files with 67 additions and 10 deletions

View File

@@ -20,7 +20,10 @@ import java.util.List;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoPage;
@@ -87,6 +90,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
return new GeoNearExecution(accessor).execute(query, countQuery);
} else if (method.isGeoNearQuery()) {
return new GeoNearExecution(accessor).execute(query);
} else if (method.isSliceQuery()) {
return new SlicedExecution(accessor.getPageable()).execute(query);
} else if (method.isCollectionQuery()) {
return new CollectionExecution(accessor.getPageable()).execute(query);
} else if (method.isPageQuery()) {
@@ -171,6 +176,41 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
}
}
/**
* {@link Execution} for {@link Slice} query methods.
*
* @author Oliver Gierke
* @since 1.5
*/
final class SlicedExecution extends Execution {
private final Pageable pageable;
SlicedExecution(Pageable pageable) {
this.pageable = pageable;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
Object execute(Query query) {
MongoEntityMetadata<?> metadata = method.getEntityInformation();
int pageSize = pageable.getPageSize();
Pageable slicePageable = new PageRequest(pageable.getPageNumber(), pageSize + 1, pageable.getSort());
List result = operations.find(query.with(slicePageable), metadata.getJavaType(), metadata.getCollectionName());
boolean hasNext = result.size() > pageSize;
return new SliceImpl<Object>(hasNext ? result.subList(0, pageSize) : result, pageable, hasNext);
}
}
/**
* {@link Execution} for pagination queries.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2014 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.
@@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoOperations;
@@ -155,8 +156,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
public void findsPagedPersons() throws Exception {
Page<Person> result = repository.findAll(new PageRequest(1, 2, Direction.ASC, "lastname", "firstname"));
assertThat(result.isFirstPage(), is(false));
assertThat(result.isLastPage(), is(false));
assertThat(result.isFirst(), is(false));
assertThat(result.isLast(), is(false));
assertThat(result, hasItems(dave, stefan));
}
@@ -165,8 +166,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname",
"firstname"));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(false));
assertThat(page.isFirst(), is(true));
assertThat(page.isLast(), is(false));
assertThat(page.getNumberOfElements(), is(2));
assertThat(page, hasItems(carter, stefan));
}
@@ -176,8 +177,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC,
"lastname", "firstname"));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(false));
assertThat(page.isFirst(), is(true));
assertThat(page.isLast(), is(false));
assertThat(page.getNumberOfElements(), is(2));
assertThat(page, hasItems(carter, stefan));
}
@@ -301,8 +302,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
Page<Person> page = repository.findAll(person.lastname.contains("a"), new PageRequest(0, 2, Direction.ASC,
"lastname"));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(false));
assertThat(page.isFirst(), is(true));
assertThat(page.isLast(), is(false));
assertThat(page.getNumberOfElements(), is(2));
assertThat(page, hasItems(carter, stefan));
}
@@ -738,4 +739,15 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result.size(), is(1));
assertThat(result.get(0), is(dave));
}
/**
* @see DATAMONGO-870
*/
@Test
public void findsSliceOfPersons() {
Slice<Person> result = repository.findByAgeGreaterThan(40, new PageRequest(0, 2, Direction.DESC, "firstname"));
assertThat(result.hasNext(), is(true));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2014 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.
@@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.geo.Box;
import org.springframework.data.mongodb.core.geo.Circle;
@@ -245,4 +246,8 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
*/
List<Person> findByFirstnameContainingIgnoreCase(String firstName);
/**
* @see DATAMONGO-870
*/
Slice<Person> findByAgeGreaterThan(int age, Pageable pageable);
}