Skip to content

Commit 9d51ea4

Browse files
christophstroblmp911de
authored andcommitted
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.
1 parent f4a5482 commit 9d51ea4

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2015 the original author or authors.
2+
* Copyright 2013-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -352,6 +352,7 @@ protected static Object toMongoExpression(AggregationOperationContext context, S
352352
*
353353
* @author Oliver Gierke
354354
* @author Thomas Darimont
355+
* @author Christoph Strobl
355356
*/
356357
public static class ProjectionOperationBuilder extends AbstractProjectionOperationBuilder {
357358

@@ -566,6 +567,31 @@ public ProjectionOperationBuilder size() {
566567
return project("size");
567568
}
568569

570+
/**
571+
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
572+
* If {@literal n} is positive, $slice returns up to the first n elements in the array. <br />
573+
* If {@literal n} is negative, $slice returns up to the last n elements in the array.
574+
*
575+
* @param count max number of elements.
576+
* @return never {@literal null}.
577+
* @since 1.10
578+
*/
579+
public ProjectionOperationBuilder slice(int count) {
580+
return project("slice", count);
581+
}
582+
583+
/**
584+
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
585+
*
586+
* @param count max number of elements. Must not be negative.
587+
* @param offset the offset within the array to start from.
588+
* @return never {@literal null}.
589+
* @since 1.10
590+
*/
591+
public ProjectionOperationBuilder slice(int count, int offset) {
592+
return project("slice", offset, count);
593+
}
594+
569595
/*
570596
* (non-Javadoc)
571597
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,27 @@ public void outShouldOutBeTheLastOperation() {
12281228
skip(100));
12291229
}
12301230

1231+
/**
1232+
* @see DATAMONGO-1457
1233+
*/
1234+
@Test
1235+
public void sliceShouldBeAppliedCorrectly() {
1236+
1237+
assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO));
1238+
1239+
createUserWithLikesDocuments();
1240+
1241+
TypedAggregation<UserWithLikes> agg = newAggregation(UserWithLikes.class, match(new Criteria()),
1242+
project().and("likes").slice(2));
1243+
1244+
AggregationResults<UserWithLikes> result = mongoTemplate.aggregate(agg, UserWithLikes.class);
1245+
1246+
assertThat(result.getMappedResults(), hasSize(9));
1247+
for (UserWithLikes user : result) {
1248+
assertThat(user.likes.size() <= 2, is(true));
1249+
}
1250+
}
1251+
12311252
private void createUsersWithReferencedPersons() {
12321253

12331254
mongoTemplate.dropCollection(User.class);

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2015 the original author or authors.
2+
* Copyright 2013-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
3636
*
3737
* @author Oliver Gierke
3838
* @author Thomas Darimont
39+
* @author Christoph Strobl
3940
*/
4041
public class ProjectionOperationUnitTests {
4142

@@ -371,6 +372,36 @@ public void shouldRenderGenericSizeExpressionInProjection() {
371372
assertThat(projected.get("tags_count"), is((Object) new BasicDBObject("$size", Arrays.asList("$tags"))));
372373
}
373374

375+
/**
376+
* @see DATAMONGO-1457
377+
*/
378+
@Test
379+
public void shouldRenderSliceCorrectly() throws Exception {
380+
381+
ProjectionOperation operation = Aggregation.project().and("field").slice(10).as("renamed");
382+
383+
DBObject dbObject = operation.toDBObject(Aggregation.DEFAULT_CONTEXT);
384+
DBObject projected = exctractOperation("$project", dbObject);
385+
386+
assertThat(projected.get("renamed"),
387+
is((Object) new BasicDBObject("$slice", Arrays.<Object> asList("$field", 10))));
388+
}
389+
390+
/**
391+
* @see DATAMONGO-1457
392+
*/
393+
@Test
394+
public void shouldRenderSliceWithPositionCorrectly() throws Exception {
395+
396+
ProjectionOperation operation = Aggregation.project().and("field").slice(10, 5).as("renamed");
397+
398+
DBObject dbObject = operation.toDBObject(Aggregation.DEFAULT_CONTEXT);
399+
DBObject projected = exctractOperation("$project", dbObject);
400+
401+
assertThat(projected.get("renamed"),
402+
is((Object) new BasicDBObject("$slice", Arrays.<Object> asList("$field", 5, 10))));
403+
}
404+
374405
private static DBObject exctractOperation(String field, DBObject fromProjectClause) {
375406
return (DBObject) fromProjectClause.get(field);
376407
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013 the original author or authors.
2+
* Copyright 2013-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,16 +20,23 @@
2020
import java.util.HashSet;
2121
import java.util.Set;
2222

23+
import lombok.Data;
24+
import lombok.NoArgsConstructor;
25+
2326
/**
2427
* @author Thomas Darimont
28+
* @author Christoph Strobl
2529
*/
30+
@Data
31+
@NoArgsConstructor
2632
public class UserWithLikes {
2733

2834
String id;
2935
Date joined;
3036
Set<String> likes = new HashSet<String>();
3137

3238
public UserWithLikes(String id, Date joined, String... likes) {
39+
3340
this.id = id;
3441
this.joined = joined;
3542
this.likes = new HashSet<String>(Arrays.asList(likes));

0 commit comments

Comments
 (0)