Skip to content

Commit 714b23e

Browse files
christophstroblmp911de
authored andcommitted
Add support for $sortArray aggregation operator.
See #4139 Original pull request: #4182.
1 parent d4a6614 commit 714b23e

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

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

+78
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.bson.Document;
2525
import org.springframework.data.domain.Range;
26+
import org.springframework.data.domain.Sort;
2627
import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.AsBuilder;
2728
import org.springframework.data.mongodb.core.aggregation.ArrayOperators.Reduce.PropertyExpression;
2829
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
@@ -315,6 +316,21 @@ public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(PropertyExpression.
315316
.withInitialValue(initialValue).reduce(expressions);
316317
}
317318

319+
/**
320+
* Creates new {@link AggregationExpression} that takes the associated array and sorts it by the given {@link Sort order}.
321+
*
322+
* @return new instance of {@link SortArray}.
323+
* @since 4.0
324+
*/
325+
public SortArray sort(Sort sort) {
326+
327+
if (usesFieldRef()) {
328+
return SortArray.sortArrayOf(fieldReference).by(sort);
329+
}
330+
331+
return (usesExpression() ? SortArray.sortArrayOf(expression) : SortArray.sortArray(values)).by(sort);
332+
}
333+
318334
/**
319335
* Creates new {@link AggregationExpression} that transposes an array of input arrays so that the first element of
320336
* the output array would be an array containing, the first element of the first input array, the first element of
@@ -1915,4 +1931,66 @@ protected String getMongoMethod() {
19151931
return "$last";
19161932
}
19171933
}
1934+
1935+
/**
1936+
* {@link AggregationExpression} for {@code $sortArray} that sorts elements in an array. <br />
1937+
*
1938+
* @author Christoph Strobl
1939+
* @since 4.0
1940+
*/
1941+
public static class SortArray extends AbstractAggregationExpression {
1942+
1943+
private SortArray(Object value) {
1944+
super(value);
1945+
}
1946+
1947+
/**
1948+
* Returns the given array.
1949+
*
1950+
* @param array must not be {@literal null}.
1951+
* @return new instance of {@link SortArray}.
1952+
*/
1953+
public static SortArray sortArray(Object array) {
1954+
return new SortArray(Collections.singletonMap("input", array));
1955+
}
1956+
1957+
/**
1958+
* Sorts the elements in the array pointed to by the given {@link Field field reference}.
1959+
*
1960+
* @param fieldReference must not be {@literal null}.
1961+
* @return new instance of {@link SortArray}.
1962+
*/
1963+
public static SortArray sortArrayOf(String fieldReference) {
1964+
return sortArray(Fields.field(fieldReference));
1965+
}
1966+
1967+
/**
1968+
* Sorts the elements of the array computed buy the given {@link AggregationExpression expression}.
1969+
*
1970+
* @param expression must not be {@literal null}.
1971+
* @return new instance of {@link SortArray}.
1972+
*/
1973+
public static SortArray sortArrayOf(AggregationExpression expression) {
1974+
return sortArray(expression);
1975+
}
1976+
1977+
/**
1978+
* Set the order to put elements in.
1979+
*
1980+
* @param sort must not be {@literal null}.
1981+
* @return new instance of {@link SortArray}.
1982+
*/
1983+
public SortArray by(Sort sort) {
1984+
return new SortArray(append("sortBy", sort));
1985+
}
1986+
1987+
/*
1988+
* (non-Javadoc)
1989+
* @see org.springframework.data.mongodb.core.aggregation.AbstractAggregationExpression#getMongoMethod()
1990+
*/
1991+
@Override
1992+
protected String getMongoMethod() {
1993+
return "$sortArray";
1994+
}
1995+
}
19181996
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public class MethodReferenceNode extends ExpressionNode {
142142
map.put("last", singleArgRef().forOperator("$last"));
143143
map.put("size", singleArgRef().forOperator("$size"));
144144
map.put("slice", arrayArgRef().forOperator("$slice"));
145+
map.put("sortArray", mapArgRef().forOperator("$sortArray").mappingParametersTo("input", "sortBy"));
145146
map.put("reverseArray", singleArgRef().forOperator("$reverseArray"));
146147
map.put("reduce", mapArgRef().forOperator("$reduce").mappingParametersTo("input", "initialValue", "in"));
147148
map.put("zip", mapArgRef().forOperator("$zip").mappingParametersTo("inputs", "useLongestLength", "defaults"));

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

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

2424
import org.bson.Document;
2525
import org.junit.jupiter.api.Test;
26+
import org.springframework.data.domain.Sort;
2627
import org.springframework.data.mongodb.core.aggregation.ArrayOperators.ArrayToObject;
2728

2829
/**
@@ -171,4 +172,11 @@ public void lastWithFieldReference() {
171172
assertThat(ArrayOperators.arrayOf("field").last().toDocument(Aggregation.DEFAULT_CONTEXT))
172173
.isEqualTo("{ $last : \"$field\" }");
173174
}
175+
176+
@Test // GH-4139
177+
void sortByWithFieldRef() {
178+
179+
assertThat(ArrayOperators.arrayOf("team").sort(Sort.by("name")).toDocument(Aggregation.DEFAULT_CONTEXT))
180+
.isEqualTo("{ $sortArray: { input: \"$team\", sortBy: { name: 1 } } }");
181+
}
174182
}

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

+6
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,12 @@ void shouldRenderSetField() {
12351235
assertThat(transform("setField(\"score\", 100, source)")).isEqualTo("{ $setField : { field : \"score\", value : 100, input : \"$source\" }}");
12361236
}
12371237

1238+
@Test // GH-4139
1239+
void shouldRenderSortArray() {
1240+
assertThat(transform(
1241+
"sortArray(team, new org.bson.Document(\"name\" , 1))")).isEqualTo("{ $sortArray : { input : \"$team\", sortBy : {\"name\" : 1 } }}");
1242+
}
1243+
12381244
private Document transform(String expression, Object... params) {
12391245
return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
12401246
}

0 commit comments

Comments
 (0)