diff --git a/pom.xml b/pom.xml
index 657607148e..f213d523f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index c2ff37b35c..b35a0b47f4 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index fd36f227c0..1368c9e8c6 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
../pom.xml
@@ -50,7 +50,7 @@
org.springframework.data
spring-data-mongodb
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index fc8d28a2b6..146da343ad 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index f3c85a046a..f8db2870bc 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2077-SNAPSHOT
../pom.xml
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 4913b04604..c8033be50a 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
@@ -98,6 +98,11 @@ public class MethodReferenceNode extends ExpressionNode {
map.put("strLenBytes", singleArgumentAggregationMethodReference().forOperator("$strLenBytes"));
map.put("strLenCP", singleArgumentAggregationMethodReference().forOperator("$strLenCP"));
map.put("substrCP", arrayArgumentAggregationMethodReference().forOperator("$substrCP"));
+ map.put("trim", mapArgumentAggregationMethodReference().forOperator("$trim").mappingParametersTo("input", "chars"));
+ map.put("ltrim",
+ mapArgumentAggregationMethodReference().forOperator("$ltrim").mappingParametersTo("input", "chars"));
+ map.put("rtrim",
+ mapArgumentAggregationMethodReference().forOperator("$rtrim").mappingParametersTo("input", "chars"));
// TEXT SEARCH OPERATORS
map.put("meta", singleArgumentAggregationMethodReference().forOperator("$meta"));
@@ -116,6 +121,9 @@ public class MethodReferenceNode extends ExpressionNode {
map.put("zip", mapArgumentAggregationMethodReference().forOperator("$zip").mappingParametersTo("inputs",
"useLongestLength", "defaults"));
map.put("in", arrayArgumentAggregationMethodReference().forOperator("$in"));
+ map.put("arrayToObject", singleArgumentAggregationMethodReference().forOperator("$arrayToObject"));
+ map.put("indexOfArray", arrayArgumentAggregationMethodReference().forOperator("$indexOfArray"));
+ map.put("range", arrayArgumentAggregationMethodReference().forOperator("$range"));
// VARIABLE OPERATORS
map.put("map", mapArgumentAggregationMethodReference().forOperator("$map") //
@@ -138,6 +146,15 @@ public class MethodReferenceNode extends ExpressionNode {
map.put("millisecond", singleArgumentAggregationMethodReference().forOperator("$millisecond"));
map.put("dateToString", mapArgumentAggregationMethodReference().forOperator("$dateToString") //
.mappingParametersTo("format", "date"));
+ map.put("dateFromString", mapArgumentAggregationMethodReference().forOperator("$dateFromString") //
+ .mappingParametersTo("dateString", "format", "timezone", "onError", "onNull"));
+ map.put("dateFromParts", mapArgumentAggregationMethodReference().forOperator("$dateFromParts")
+ .mappingParametersTo("year", "month", "day", "hour", "minute", "second", "milliseconds", "timezone"));
+ map.put("isoDateFromParts",
+ mapArgumentAggregationMethodReference().forOperator("$dateFromParts").mappingParametersTo("isoWeekYear",
+ "isoWeek", "isoDayOfWeek", "hour", "minute", "second", "milliseconds", "timezone"));
+ map.put("dateToParts", mapArgumentAggregationMethodReference().forOperator("$dateToParts") //
+ .mappingParametersTo("date", "timezone", "iso8601"));
map.put("isoDayOfWeek", singleArgumentAggregationMethodReference().forOperator("$isoDayOfWeek"));
map.put("isoWeek", singleArgumentAggregationMethodReference().forOperator("$isoWeek"));
map.put("isoWeekYear", singleArgumentAggregationMethodReference().forOperator("$isoWeekYear"));
@@ -162,6 +179,24 @@ public class MethodReferenceNode extends ExpressionNode {
// TYPE OPERATORS
map.put("type", singleArgumentAggregationMethodReference().forOperator("$type"));
+ // OBJECT OPERATORS
+ map.put("objectToArray", singleArgumentAggregationMethodReference().forOperator("$objectToArray"));
+ map.put("mergeObjects", arrayArgumentAggregationMethodReference().forOperator("$mergeObjects"));
+
+ // CONVERT OPERATORS
+ map.put("convert", mapArgumentAggregationMethodReference().forOperator("$convert") //
+ .mappingParametersTo("input", "to", "onError", "onNull"));
+ map.put("toBool", singleArgumentAggregationMethodReference().forOperator("$toBool"));
+ map.put("toDate", singleArgumentAggregationMethodReference().forOperator("$toDate"));
+ map.put("toDecimal", singleArgumentAggregationMethodReference().forOperator("$toDecimal"));
+ map.put("toDouble", singleArgumentAggregationMethodReference().forOperator("$toDouble"));
+ map.put("toInt", singleArgumentAggregationMethodReference().forOperator("$toInt"));
+ map.put("toLong", singleArgumentAggregationMethodReference().forOperator("$toLong"));
+ map.put("toObjectId", singleArgumentAggregationMethodReference().forOperator("$toObjectId"));
+ map.put("toString", singleArgumentAggregationMethodReference().forOperator("$toString"));
+
+
+
FUNCTIONS = Collections.unmodifiableMap(map);
}
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 09974c9836..c3b1f72285 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
@@ -719,6 +719,216 @@ public void shouldRenderMethodRefereneType() {
assertThat(transform("type(a)"), is(Document.parse("{ \"$type\" : \"$a\"}")));
}
+ @Test // DATAMONGO-2077
+ public void shouldRenderArrayToObjectWithFieldReference() {
+ assertThat(transform("arrayToObject(field)"), is(Document.parse("{ \"$arrayToObject\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderArrayToObjectWithArray() {
+
+ assertThat(transform("arrayToObject(new String[]{'key', 'value'})"),
+ is(Document.parse("{ \"$arrayToObject\" : [\"key\", \"value\"]}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderObjectToArrayWithFieldReference() {
+ assertThat(transform("objectToArray(field)"), is(Document.parse("{ \"$objectToArray\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderMergeObjects() {
+
+ assertThat(transform("mergeObjects(field1, $$ROOT)"),
+ is(Document.parse("{ \"$mergeObjects\" : [\"$field1\", \"$$ROOT\"]}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderTrimWithoutChars() {
+ assertThat(transform("trim(field)"), is(Document.parse("{ \"$trim\" : {\"input\" : \"$field\"}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderTrimWithChars() {
+
+ assertThat(transform("trim(field, 'ie')"),
+ is(Document.parse("{ \"$trim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderTrimWithCharsFromFieldReference() {
+
+ assertThat(transform("trim(field1, field2)"),
+ is(Document.parse("{ \"$trim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderLtrimWithoutChars() {
+ assertThat(transform("ltrim(field)"), is(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\"}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderLtrimWithChars() {
+
+ assertThat(transform("ltrim(field, 'ie')"),
+ is(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderLtrimWithCharsFromFieldReference() {
+
+ assertThat(transform("ltrim(field1, field2)"),
+ is(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderRtrimWithoutChars() {
+ assertThat(transform("rtrim(field)"), is(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\"}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderRtrimWithChars() {
+
+ assertThat(transform("rtrim(field, 'ie')"),
+ is(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderRtrimWithCharsFromFieldReference() {
+
+ assertThat(transform("rtrim(field1, field2)"),
+ is(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderConvertWithoutOptionalParameters() {
+
+ assertThat(transform("convert(field, 'string')"),
+ is(Document.parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"string\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderConvertWithOnError() {
+
+ assertThat(transform("convert(field, 'int', 'Not an integer.')"), is(Document
+ .parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderConvertWithOnErrorOnNull() {
+
+ assertThat(transform("convert(field, 'int', 'Not an integer.', -1)"), is(Document.parse(
+ "{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\", \"onNull\" : -1 }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToBool() {
+ assertThat(transform("toBool(field)"), is(Document.parse("{ \"$toBool\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToDate() {
+ assertThat(transform("toDate(field)"), is(Document.parse("{ \"$toDate\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToDecimal() {
+ assertThat(transform("toDecimal(field)"), is(Document.parse("{ \"$toDecimal\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToDouble() {
+ assertThat(transform("toDouble(field)"), is(Document.parse("{ \"$toDouble\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToInt() {
+ assertThat(transform("toInt(field)"), is(Document.parse("{ \"$toInt\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToLong() {
+ assertThat(transform("toLong(field)"), is(Document.parse("{ \"$toLong\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToObjectId() {
+ assertThat(transform("toObjectId(field)"), is(Document.parse("{ \"$toObjectId\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderToString() {
+ assertThat(transform("toString(field)"), is(Document.parse("{ \"$toString\" : \"$field\"}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromStringWithoutOptionalParameters() {
+
+ assertThat(transform("dateFromString(field)"),
+ is(Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromStringWithFormat() {
+
+ assertThat(transform("dateFromString(field, 'DD-MM-YYYY')"),
+ is(Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromStringWithFormatAndTimezone() {
+
+ assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC')"), is(Document.parse(
+ "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\" }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromStringWithFormatTimezoneAndOnError() {
+
+ assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1)"), is(Document.parse(
+ "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1 }}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromStringWithFormatTimezoneOnErrorAndOnNull() {
+
+ assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1, -2)"), is(Document.parse(
+ "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1, \"onNull\" : -2}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateFromParts() {
+
+ assertThat(transform("dateFromParts(y, m, d, h, mm, s, ms, 'UTC')"), is(Document.parse(
+ "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"milliseconds\" : \"$ms\", \"timezone\" : \"UTC\"}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderIsoDateFromParts() {
+
+ assertThat(transform("isoDateFromParts(y, m, d, h, mm, s, ms, 'UTC')"), is(Document.parse(
+ "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"milliseconds\" : \"$ms\", \"timezone\" : \"UTC\"}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderDateToParts() {
+
+ assertThat(transform("dateToParts(field, 'UTC', false)"), is(
+ Document.parse("{ \"$dateToParts\" : {\"date\" : \"$field\", \"timezone\" : \"UTC\", \"iso8601\" : false}}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderIndexOfArray() {
+
+ assertThat(transform("indexOfArray(field, 2)"), is(Document.parse("{ \"$indexOfArray\" : [\"$field\", 2 ]}")));
+ }
+
+ @Test // DATAMONGO-2077
+ public void shouldRenderRange() {
+
+ assertThat(transform("range(0, 10, 2)"), is(Document.parse("{ \"$range\" : [0, 10, 2 ]}")));
+ }
+
private Object transform(String expression, Object... params) {
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);