Skip to content

Commit fe7c4a9

Browse files
Add support for $integral aggregation operator.
Closes: #3721
1 parent 26f3ee7 commit fe7c4a9

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

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

+69
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,27 @@ public Floor floor() {
208208
return usesFieldRef() ? Floor.floorValueOf(fieldReference) : Floor.floorValueOf(expression);
209209
}
210210

211+
/**
212+
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
213+
*
214+
* @return new instance of {@link Integral}.
215+
* @since 3.3
216+
*/
217+
public Integral integral() {
218+
return usesFieldRef() ? Integral.integralOf(fieldReference) : Integral.integralOf(expression);
219+
}
220+
221+
/**
222+
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
223+
*
224+
* @param unit the unit of measure.
225+
* @return new instance of {@link Integral}.
226+
* @since 3.3
227+
*/
228+
public Integral integral(String unit) {
229+
return integral().unit(unit);
230+
}
231+
211232
/**
212233
* Creates new {@link AggregationExpression} that calculates the natural logarithm ln (i.e loge) of the assoicated
213234
* number.
@@ -1665,4 +1686,52 @@ protected String getMongoMethod() {
16651686
return "$round";
16661687
}
16671688
}
1689+
1690+
/**
1691+
* Value object to represent an {@link AggregationExpression expression} that calculates the approximation for the mathematical integral value.
1692+
*
1693+
* @author Christoph Strobl
1694+
* @since 3.3
1695+
*/
1696+
public static class Integral extends AbstractAggregationExpression {
1697+
1698+
private Integral(Object value) {
1699+
super(value);
1700+
}
1701+
1702+
/**
1703+
* Create a new instance of {@link Integral} for the value stored at the given field holding a numeric value.
1704+
*
1705+
* @param fieldReference must not be {@literal null}.
1706+
* @return new instance of {@link Integral}.
1707+
*/
1708+
public static Integral integralOf(String fieldReference) {
1709+
return new Integral(Collections.singletonMap("input", Fields.field(fieldReference)));
1710+
}
1711+
1712+
/**
1713+
* Create a new instance of {@link Integral} for the value provided by the given expression that resolves to a numeric value.
1714+
*
1715+
* @param expression must not be {@literal null}.
1716+
* @return new instance of {@link Integral}.
1717+
*/
1718+
public static Integral integralOf(AggregationExpression expression) {
1719+
return new Integral(Collections.singletonMap("input", expression));
1720+
}
1721+
1722+
/**
1723+
* Set the unit of measure.
1724+
*
1725+
* @param unit the unit of measure.
1726+
* @return new instance of {@link Integral}.
1727+
*/
1728+
public Integral unit(String unit) {
1729+
return new Integral(append("unit", unit));
1730+
}
1731+
1732+
@Override
1733+
protected String getMongoMethod() {
1734+
return "$integral";
1735+
}
1736+
}
16681737
}

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("integral", mapArgRef().forOperator("$integral").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

+10
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,14 @@ void roundShouldWithPlaceFromExpression() {
5959
.toDocument(Aggregation.DEFAULT_CONTEXT))
6060
.isEqualTo(new Document("$round", Arrays.asList("$field", new Document("$first", "$source"))));
6161
}
62+
63+
@Test // GH-3721
64+
void rendersIntegral() {
65+
assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\" } }"));
66+
}
67+
68+
@Test // GH-3721
69+
void rendersIntegralWithUnit() {
70+
assertThat(valueOf("kilowatts").integral("hour").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }"));
71+
}
6272
}

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

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

949+
@Test // GH-3721
950+
public void shouldIntegral() {
951+
assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}"));
952+
}
953+
954+
@Test // GH-3721
955+
public void shouldIntegralWithUnit() {
956+
assertThat(transform("integral(field, 'hour')")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"));
957+
}
958+
949959
private Object transform(String expression, Object... params) {
950960
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
951961
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);

0 commit comments

Comments
 (0)