Skip to content

Commit bcbefa9

Browse files
Support aggregation operators $first and $last via expression method reference.
This commit registers the first(...) and last(...) methods for transformation via SpEL. Also update reference and java documentation and add issue reference to tests. Original Pull Request: #3866
1 parent a224353 commit bcbefa9

File tree

5 files changed

+34
-16
lines changed

5 files changed

+34
-16
lines changed

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
* @author Christoph Strobl
3636
* @author Mark Paluch
3737
* @author Shashank Sharma
38+
* @author Divya Srivastava
3839
* @since 1.0
3940
*/
4041
public class ArrayOperators {
@@ -364,10 +365,11 @@ public ArrayToObject toObject() {
364365
}
365366

366367
/**
367-
* Creates new {@link AggregationExpression} that return the first element in the given array.
368+
* Creates new {@link AggregationExpression} that return the first element in the associated array.
368369
* <strong>NOTE:</strong> Requires MongoDB 4.4 or later.
369370
*
370371
* @return new instance of {@link First}.
372+
* @since 3.4
371373
*/
372374
public First first() {
373375

@@ -382,7 +384,8 @@ public First first() {
382384
* Creates new {@link AggregationExpression} that return the last element in the given array.
383385
* <strong>NOTE:</strong> Requires MongoDB 4.4 or later.
384386
*
385-
* @return new instance of {@link First}.
387+
* @return new instance of {@link Last}.
388+
* @since 3.4
386389
*/
387390
public Last last() {
388391

@@ -1847,6 +1850,9 @@ protected String getMongoMethod() {
18471850
* {@link AggregationExpression} for {@code $first} that returns the first element in an array. <br />
18481851
* <strong>NOTE:</strong> Requires MongoDB 4.4 or later.
18491852
*
1853+
* @author Divya Srivastava
1854+
* @author Christoph Strobl
1855+
* @since 3.4
18501856
*/
18511857
public static class First extends AbstractAggregationExpression {
18521858

@@ -1875,7 +1881,7 @@ public static First firstOf(String fieldReference) {
18751881
}
18761882

18771883
/**
1878-
* Returns the first element of the array of the given {@link AggregationExpression expression}.
1884+
* Returns the first element of the array computed by the given {@link AggregationExpression expression}.
18791885
*
18801886
* @param expression must not be {@literal null}.
18811887
* @return new instance of {@link First}.
@@ -1898,6 +1904,9 @@ protected String getMongoMethod() {
18981904
* {@link AggregationExpression} for {@code $last} that returns the last element in an array. <br />
18991905
* <strong>NOTE:</strong> Requires MongoDB 4.4 or later.
19001906
*
1907+
* @author Divya Srivastava
1908+
* @author Christoph Strobl
1909+
* @since 3.4
19011910
*/
19021911
public static class Last extends AbstractAggregationExpression {
19031912

@@ -1906,7 +1915,7 @@ private Last(Object value) {
19061915
}
19071916

19081917
/**
1909-
* Returns the first element in the given array.
1918+
* Returns the last element in the given array.
19101919
*
19111920
* @param array must not be {@literal null}.
19121921
* @return new instance of {@link Last}.
@@ -1926,7 +1935,7 @@ public static Last lastOf(String fieldReference) {
19261935
}
19271936

19281937
/**
1929-
* Returns the last element of the array of the given {@link AggregationExpression expression}.
1938+
* Returns the last element of the array computed buy the given {@link AggregationExpression expression}.
19301939
*
19311940
* @param expression must not be {@literal null}.
19321941
* @return new instance of {@link Last}.
@@ -1944,5 +1953,4 @@ protected String getMongoMethod() {
19441953
return "$last";
19451954
}
19461955
}
1947-
19481956
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java

+2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ public class MethodReferenceNode extends ExpressionNode {
137137
map.put("concatArrays", arrayArgRef().forOperator("$concatArrays"));
138138
map.put("filter", mapArgRef().forOperator("$filter") //
139139
.mappingParametersTo("input", "as", "cond"));
140+
map.put("first", singleArgRef().forOperator("$first"));
140141
map.put("isArray", singleArgRef().forOperator("$isArray"));
142+
map.put("last", singleArgRef().forOperator("$last"));
141143
map.put("size", singleArgRef().forOperator("$size"));
142144
map.put("slice", arrayArgRef().forOperator("$slice"));
143145
map.put("reverseArray", singleArgRef().forOperator("$reverseArray"));

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

+7-8
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323

2424
import org.bson.Document;
2525
import org.junit.jupiter.api.Test;
26-
2726
import org.springframework.data.mongodb.core.aggregation.ArrayOperators.ArrayToObject;
2827

2928
/**
3029
* Unit tests for {@link ArrayOperators}
3130
*
3231
* @author Christoph Strobl
3332
* @author Shashank Sharma
33+
* @author Divya Srivastava
3434
* @currentRead Royal Assassin - Robin Hobb
3535
*/
3636
public class ArrayOperatorsUnitTests {
@@ -130,46 +130,45 @@ public void inWithValueList() {
130130
.isEqualTo("{ \"$in\" : [\"$userName\", " + VALUE_LIST_STRING + "] }");
131131
}
132132

133-
@Test
133+
@Test // GH-3694
134134
public void firstWithValueList() {
135135

136136
assertThat(ArrayOperators.arrayOf(VALUE_LIST).first().toDocument(Aggregation.DEFAULT_CONTEXT))
137137
.isEqualTo("{ \"$first\" : " + VALUE_LIST_STRING + "}");
138138
}
139139

140-
@Test
140+
@Test // GH-3694
141141
public void firstWithExpression() {
142142

143143
assertThat(ArrayOperators.arrayOf(EXPRESSION).first().toDocument(Aggregation.DEFAULT_CONTEXT))
144144
.isEqualTo("{ \"$first\" : " + EXPRESSION_STRING + "}");
145145
}
146146

147-
@Test
147+
@Test // GH-3694
148148
public void firstWithFieldReference() {
149149

150150
assertThat(ArrayOperators.arrayOf("field").first().toDocument(Aggregation.DEFAULT_CONTEXT))
151151
.isEqualTo("{ $first : \"$field\" }");
152152
}
153153

154-
@Test
154+
@Test // GH-3694
155155
public void lastWithValueList() {
156156

157157
assertThat(ArrayOperators.arrayOf(VALUE_LIST).last().toDocument(Aggregation.DEFAULT_CONTEXT))
158158
.isEqualTo("{ \"$last\" : " + VALUE_LIST_STRING + "}");
159159
}
160160

161-
@Test
161+
@Test // GH-3694
162162
public void lastWithExpression() {
163163

164164
assertThat(ArrayOperators.arrayOf(EXPRESSION).last().toDocument(Aggregation.DEFAULT_CONTEXT))
165165
.isEqualTo("{ \"$last\" : " + EXPRESSION_STRING + "}");
166166
}
167167

168-
@Test
168+
@Test // GH-3694
169169
public void lastWithFieldReference() {
170170

171171
assertThat(ArrayOperators.arrayOf("field").last().toDocument(Aggregation.DEFAULT_CONTEXT))
172172
.isEqualTo("{ $last : \"$field\" }");
173173
}
174-
175174
}

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,16 @@ void shouldRenderMethodReferenceNodeArrayElemAt() {
411411
assertThat(transform("arrayElemAt(a, 10)")).isEqualTo("{ \"$arrayElemAt\" : [ \"$a\" , 10]}");
412412
}
413413

414+
@Test // GH-3694
415+
void shouldRenderMethodReferenceNodeFirst() {
416+
assertThat(transform("first(a)")).isEqualTo("{ \"$first\" : \"$a\" }");
417+
}
418+
419+
@Test // GH-3694
420+
void shouldRenderMethodReferenceNodeLast() {
421+
assertThat(transform("last(a)")).isEqualTo("{ \"$last\" : \"$a\" }");
422+
}
423+
414424
@Test // DATAMONGO-1530
415425
void shouldRenderMethodReferenceNodeConcatArrays() {
416426
assertThat(transform("concatArrays(a, b, c)"))
@@ -879,7 +889,6 @@ void shouldRenderReplaceAll() {
879889
.isEqualTo("{ \"$replaceAll\" : {\"input\" : \"$field\" , \"find\" : \"bar\" , \"replacement\" : \"baz\"}}");
880890
}
881891

882-
883892
@Test // DATAMONGO-2077
884893
void shouldRenderConvertWithoutOptionalParameters() {
885894

src/main/asciidoc/reference/aggregation-framework.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ At the time of this writing, we provide support for the following Aggregation Op
9494
| `eq` (+++*+++ via `is`), `gt`, `gte`, `lt`, `lte`, `ne`
9595

9696
| Array Aggregation Operators
97-
| `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `in`, `indexOfArray`, `isArray`, `range`, `reverseArray`, `reduce`, `size`, `slice`, `zip`
97+
| `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `first`, `in`, `indexOfArray`, `isArray`, `last`, range`, `reverseArray`, `reduce`, `size`, `slice`, `zip`
9898

9999
| Literal Operators
100100
| `literal`

0 commit comments

Comments
 (0)