diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java index 996e82a98..976d73439 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.aggregation; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import org.bson.Document; import org.springframework.util.Assert; @@ -124,6 +125,16 @@ public class ObjectOperators { public ObjectToArray toArray() { return ObjectToArray.toArray(value); } + + /** + * Creates new {@link GetField aggregation expression} that takes the associated value and obtains the value of the + * field with matching name. + * + * @since 4.0 + */ + public GetField getField(String fieldName) { + return GetField.getField(fieldName).from(value); + } } /** @@ -283,4 +294,42 @@ public class ObjectOperators { return "$objectToArray"; } } + + /** + * {@link AggregationExpression} for {@code $getField}. + * + * @author Christoph Strobl + * @since 4.0 + */ + public static class GetField extends AbstractAggregationExpression { + + protected GetField(Object value) { + super(value); + } + + public static GetField getField(String fieldName) { + return new GetField(Collections.singletonMap("field", fieldName)); + } + + public static GetField getField(Field field) { + return getField(field.getTarget()); + } + + public GetField from(String fieldRef) { + return from(Fields.field(fieldRef)); + } + + public GetField from(AggregationExpression expression) { + return from((Object) expression); + } + + private GetField from(Object fieldRef) { + return new GetField(append("input", fieldRef)); + } + + @Override + protected String getMongoMethod() { + return "$getField"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 23e558a1c..32e846966 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -165,8 +165,8 @@ public class MethodReferenceNode extends ExpressionNode { mapArgRef().forOperator("$dateSubtract").mappingParametersTo("startDate", "unit", "amount", "timezone")); map.put("dateDiff", mapArgRef().forOperator("$dateDiff").mappingParametersTo("startDate", "endDate", "unit", "timezone", "startOfWeek")); - map.put("dateTrunc", - mapArgRef().forOperator("$dateTrunc").mappingParametersTo("date", "unit", "binSize", "startOfWeek", "timezone")); + map.put("dateTrunc", mapArgRef().forOperator("$dateTrunc").mappingParametersTo("date", "unit", "binSize", + "startOfWeek", "timezone")); map.put("dayOfYear", singleArgRef().forOperator("$dayOfYear")); map.put("dayOfMonth", singleArgRef().forOperator("$dayOfMonth")); map.put("dayOfWeek", singleArgRef().forOperator("$dayOfWeek")); @@ -209,13 +209,6 @@ public class MethodReferenceNode extends ExpressionNode { map.put("stdDevSamp", arrayArgRef().forOperator("$stdDevSamp")); map.put("covariancePop", arrayArgRef().forOperator("$covariancePop")); map.put("covarianceSamp", arrayArgRef().forOperator("$covarianceSamp")); - - // TYPE OPERATORS - map.put("type", singleArgRef().forOperator("$type")); - - // OBJECT OPERATORS - map.put("objectToArray", singleArgRef().forOperator("$objectToArray")); - map.put("mergeObjects", arrayArgRef().forOperator("$mergeObjects")); map.put("bottom", mapArgRef().forOperator("$bottom") // .mappingParametersTo("output", "sortBy")); map.put("bottomN", mapArgRef().forOperator("$bottomN") // @@ -233,6 +226,14 @@ public class MethodReferenceNode extends ExpressionNode { map.put("minN", mapArgRef().forOperator("$minN") // .mappingParametersTo("n", "input")); + // TYPE OPERATORS + map.put("type", singleArgRef().forOperator("$type")); + + // OBJECT OPERATORS + map.put("objectToArray", singleArgRef().forOperator("$objectToArray")); + map.put("mergeObjects", arrayArgRef().forOperator("$mergeObjects")); + map.put("getField", mapArgRef().forOperator("$getField").mappingParametersTo("field", "input")); + // CONVERT OPERATORS map.put("convert", mapArgRef().forOperator("$convert") // .mappingParametersTo("input", "to", "onError", "onNull")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java index f8f94f888..1854a94fc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java @@ -102,4 +102,11 @@ public class ObjectOperatorsUnitTests { .isEqualTo(Document.parse("{ $objectToArray : " + EXPRESSION_STRING + " }")); } + @Test // GH-4139 + public void getField() { + + assertThat(ObjectOperators.valueOf("batman").getField("robin").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $getField : { field : \"robin\", input : \"$batman\" }}")); + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index b80963828..5f54bc5d1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1225,6 +1225,11 @@ public class SpelExpressionTransformerUnitTests { assertThat(transform("dateTrunc(purchaseDate, \"week\", 2, \"monday\")")).isEqualTo("{ $dateTrunc : { date : \"$purchaseDate\", unit : \"week\", binSize : 2, startOfWeek : \"monday\" }}"); } + @Test // GH-4139 + void shouldRenderGetField() { + assertThat(transform("getField(\"score\", source)")).isEqualTo("{ $getField : { field : \"score\", input : \"$source\" }}"); + } + private Document transform(String expression, Object... params) { return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); }