Skip to content

Commit 276e4eb

Browse files
Add support for $derivative aggregation operator.
Closes: #3716
1 parent 9cb93fa commit 276e4eb

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

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

+55
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevPop;
2525
import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevSamp;
2626
import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Sum;
27+
import org.springframework.lang.Nullable;
2728
import org.springframework.util.Assert;
29+
import org.springframework.util.StringUtils;
2830

2931
/**
3032
* Gateway to {@literal Arithmetic} aggregation operations that perform math operations on numbers.
@@ -532,6 +534,31 @@ public Round roundToPlace(int place) {
532534
return round().place(place);
533535
}
534536

537+
/**
538+
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
539+
*
540+
* @return new instance of {@link Derivative}.
541+
* @since 3.3
542+
*/
543+
public Derivative derivative() {
544+
return derivative(null);
545+
}
546+
547+
/**
548+
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
549+
*
550+
* @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be
551+
* {@literal null}.
552+
* @return new instance of {@link Derivative}.
553+
* @since 3.3
554+
*/
555+
public Derivative derivative(@Nullable String unit) {
556+
557+
Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference)
558+
: Derivative.derivativeOf(expression);
559+
return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative;
560+
}
561+
535562
private boolean usesFieldRef() {
536563
return fieldReference != null;
537564
}
@@ -1665,4 +1692,32 @@ protected String getMongoMethod() {
16651692
return "$round";
16661693
}
16671694
}
1695+
1696+
public static class Derivative extends AbstractAggregationExpression {
1697+
1698+
private Derivative(Object value) {
1699+
super(value);
1700+
}
1701+
1702+
public static Derivative derivativeOf(String fieldReference) {
1703+
return new Derivative(Collections.singletonMap("input", Fields.field(fieldReference)));
1704+
}
1705+
1706+
public static Derivative derivativeOf(AggregationExpression expression) {
1707+
return new Derivative(Collections.singletonMap("input", expression));
1708+
}
1709+
1710+
public static Derivative derivativeOfValue(Number value) {
1711+
return new Derivative(Collections.singletonMap("input", value));
1712+
}
1713+
1714+
public Derivative unit(String unit) {
1715+
return new Derivative(append("unit", unit));
1716+
}
1717+
1718+
@Override
1719+
protected String getMongoMethod() {
1720+
return "$derivative";
1721+
}
1722+
}
16681723
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public class MethodReferenceNode extends ExpressionNode {
8585
map.put("subtract", arrayArgRef().forOperator("$subtract"));
8686
map.put("trunc", singleArgRef().forOperator("$trunc"));
8787
map.put("round", arrayArgRef().forOperator("$round"));
88+
map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit"));
8889

8990
// STRING OPERATORS
9091
map.put("concat", arrayArgRef().forOperator("$concat"));

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

+7
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,11 @@ void roundShouldWithPlaceFromExpression() {
5959
.toDocument(Aggregation.DEFAULT_CONTEXT))
6060
.isEqualTo(new Document("$round", Arrays.asList("$field", new Document("$first", "$source"))));
6161
}
62+
63+
@Test // GH-3716
64+
void rendersDerivativeCorrectly() {
65+
66+
assertThat(valueOf("miles").derivative("hour").toDocument(Aggregation.DEFAULT_CONTEXT))
67+
.isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }"));
68+
}
6269
}

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

+5
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,11 @@ public void shouldRenderRoundWithPlace() {
946946
assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}"));
947947
}
948948

949+
@Test // GH-3716
950+
void shouldRenderDerivative() {
951+
assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }"));
952+
}
953+
949954
private Object transform(String expression, Object... params) {
950955
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
951956
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);

0 commit comments

Comments
 (0)