diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java index af01e3cebe..068b5bf717 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java @@ -1032,35 +1032,68 @@ public Slice itemCount(int nrElements) { return new Slice(append(nrElements)); } + /** + * Slice the number of elements. + * + * @param nrElements An {@link AggregationExpression} that evaluates to a numeric value used as item count. + * @return new instance of {@link Slice}. + * @since 4.5 + */ + public Slice itemCount(AggregationExpression nrElements) { + return new Slice(append(nrElements)); + } + /** * Slice using offset and count. * * @param position the start position * @return new instance of {@link SliceElementsBuilder} to create {@link Slice}. */ - public SliceElementsBuilder offset(final int position) { - - return new SliceElementsBuilder() { + public SliceElementsBuilder offset(int position) { + return new SliceElementsBuilder(position); + } - @Override - public Slice itemCount(int nrElements) { - return new Slice(append(position)).itemCount(nrElements); - } - }; + /** + * Slice using offset and count. + * + * @param position the start position + * @return new instance of {@link SliceElementsBuilder} to create {@link Slice}. + */ + public SliceElementsBuilder offset(AggregationExpression position) { + return new SliceElementsBuilder(position); } /** * @author Christoph Strobl */ - public interface SliceElementsBuilder { + public class SliceElementsBuilder { + + private final Object position; + + SliceElementsBuilder(Object position) { + this.position = position; + } /** * Set the number of elements given {@literal nrElements}. * * @param nrElements - * @return + * @return new instance of {@link Slice}. */ - Slice itemCount(int nrElements); + public Slice itemCount(int nrElements) { + return new Slice(append(position)).itemCount(nrElements); + } + + /** + * Slice the number of elements. + * + * @param nrElements An {@link AggregationExpression} that evaluates to a numeric value used as item count. + * @return new instance of {@link Slice}. + * @since 4.5 + */ + public Slice itemCount(AggregationExpression nrElements) { + return new Slice(append(position)).itemCount(nrElements); + } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index ded639f204..09a0ebbcd0 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -29,6 +29,7 @@ import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; import org.springframework.data.mongodb.core.DocumentTestUtils; +import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators.Subtract; import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Reduce; import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Reduce.PropertyExpression; import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Reduce.Variable; @@ -1064,6 +1065,17 @@ void shouldRenderSliceWithPositionAggregationExpression() { assertThat(agg).isEqualTo(Document.parse("{ $project: { threeFavorites: { $slice: [ \"$favorites\", 2, 3 ] } } }")); } + @Test // DATAMONGO-4857 + void shouldRenderSliceWithExpressions() { + + Document agg = project().and(ArrayOperators.arrayOf("favorites").slice() + .offset(Subtract.valueOf(ArrayOperators.Size.lengthOfArray("myArray")).subtract(1)) + .itemCount(ArithmeticOperators.rand())).as("threeFavorites").toDocument(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg).isEqualTo(Document.parse( + "{ $project: { threeFavorites: { $slice: [ \"$favorites\", { \"$subtract\": [ {\"$size\": \"$myArray\"}, 1]}, { $rand : {} } ] } } }")); + } + @Test // DATAMONGO-1536 void shouldRenderLiteral() {