DATAMONGO-1457 - Add support for $slice in aggregation.

We now support $slice in aggregation projections via the ProjectionOperationBuilder.

    Aggregation.project().and("field").slice(10, 20)

Original pull request: #372.
This commit is contained in:
Christoph Strobl
2016-07-07 14:41:12 +02:00
committed by Mark Paluch
parent f4a5482005
commit 9d51ea4c01
4 changed files with 88 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-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.
@@ -352,6 +352,7 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
public static class ProjectionOperationBuilder extends AbstractProjectionOperationBuilder {
@@ -566,6 +567,31 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
return project("size");
}
/**
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
* If {@literal n} is positive, $slice returns up to the first n elements in the array. <br />
* If {@literal n} is negative, $slice returns up to the last n elements in the array.
*
* @param count max number of elements.
* @return never {@literal null}.
* @since 1.10
*/
public ProjectionOperationBuilder slice(int count) {
return project("slice", count);
}
/**
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
*
* @param count max number of elements. Must not be negative.
* @param offset the offset within the array to start from.
* @return never {@literal null}.
* @since 1.10
*/
public ProjectionOperationBuilder slice(int count, int offset) {
return project("slice", offset, count);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)

View File

@@ -1228,6 +1228,27 @@ public class AggregationTests {
skip(100));
}
/**
* @see DATAMONGO-1457
*/
@Test
public void sliceShouldBeAppliedCorrectly() {
assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO));
createUserWithLikesDocuments();
TypedAggregation<UserWithLikes> agg = newAggregation(UserWithLikes.class, match(new Criteria()),
project().and("likes").slice(2));
AggregationResults<UserWithLikes> result = mongoTemplate.aggregate(agg, UserWithLikes.class);
assertThat(result.getMappedResults(), hasSize(9));
for (UserWithLikes user : result) {
assertThat(user.likes.size() <= 2, is(true));
}
}
private void createUsersWithReferencedPersons() {
mongoTemplate.dropCollection(User.class);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-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.
@@ -36,6 +36,7 @@ import com.mongodb.DBObject;
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class ProjectionOperationUnitTests {
@@ -371,6 +372,36 @@ public class ProjectionOperationUnitTests {
assertThat(projected.get("tags_count"), is((Object) new BasicDBObject("$size", Arrays.asList("$tags"))));
}
/**
* @see DATAMONGO-1457
*/
@Test
public void shouldRenderSliceCorrectly() throws Exception {
ProjectionOperation operation = Aggregation.project().and("field").slice(10).as("renamed");
DBObject dbObject = operation.toDBObject(Aggregation.DEFAULT_CONTEXT);
DBObject projected = exctractOperation("$project", dbObject);
assertThat(projected.get("renamed"),
is((Object) new BasicDBObject("$slice", Arrays.<Object> asList("$field", 10))));
}
/**
* @see DATAMONGO-1457
*/
@Test
public void shouldRenderSliceWithPositionCorrectly() throws Exception {
ProjectionOperation operation = Aggregation.project().and("field").slice(10, 5).as("renamed");
DBObject dbObject = operation.toDBObject(Aggregation.DEFAULT_CONTEXT);
DBObject projected = exctractOperation("$project", dbObject);
assertThat(projected.get("renamed"),
is((Object) new BasicDBObject("$slice", Arrays.<Object> asList("$field", 5, 10))));
}
private static DBObject exctractOperation(String field, DBObject fromProjectClause) {
return (DBObject) fromProjectClause.get(field);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-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.
@@ -20,9 +20,15 @@ import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Thomas Darimont
* @author Christoph Strobl
*/
@Data
@NoArgsConstructor
public class UserWithLikes {
String id;
@@ -30,6 +36,7 @@ public class UserWithLikes {
Set<String> likes = new HashSet<String>();
public UserWithLikes(String id, Date joined, String... likes) {
this.id = id;
this.joined = joined;
this.likes = new HashSet<String>(Arrays.asList(likes));