Skip to content

Commit df2b2a2

Browse files
christophstroblmp911de
authored andcommitted
Add support for $integral aggregation operator.
Closes: #3721 Original pull request: #3746.
1 parent fd0a402 commit df2b2a2

File tree

4 files changed

+100
-8
lines changed

4 files changed

+100
-8
lines changed

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

+79-8
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,27 @@ public Floor floor() {
216216
return usesFieldRef() ? Floor.floorValueOf(fieldReference) : Floor.floorValueOf(expression);
217217
}
218218

219+
/**
220+
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
221+
*
222+
* @return new instance of {@link Integral}.
223+
* @since 3.3
224+
*/
225+
public Integral integral() {
226+
return usesFieldRef() ? Integral.integralOf(fieldReference) : Integral.integralOf(expression);
227+
}
228+
229+
/**
230+
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
231+
*
232+
* @param unit the unit of measure.
233+
* @return new instance of {@link Integral}.
234+
* @since 3.3
235+
*/
236+
public Integral integral(String unit) {
237+
return integral().unit(unit);
238+
}
239+
219240
/**
220241
* Creates new {@link AggregationExpression} that calculates the natural logarithm ln (i.e loge) of the assoicated
221242
* number.
@@ -520,8 +541,8 @@ public StdDevSamp stdDevSamp() {
520541
}
521542

522543
/**
523-
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given
524-
* field to calculate the population covariance of the two.
544+
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the
545+
* given field to calculate the population covariance of the two.
525546
*
526547
* @param fieldReference must not be {@literal null}.
527548
* @return new instance of {@link CovariancePop}.
@@ -532,8 +553,8 @@ public CovariancePop covariancePop(String fieldReference) {
532553
}
533554

534555
/**
535-
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given
536-
* {@link AggregationExpression expression} to calculate the population covariance of the two.
556+
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the
557+
* given {@link AggregationExpression expression} to calculate the population covariance of the two.
537558
*
538559
* @param expression must not be {@literal null}.
539560
* @return new instance of {@link CovariancePop}.
@@ -548,8 +569,8 @@ private CovariancePop covariancePop() {
548569
}
549570

550571
/**
551-
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given
552-
* field to calculate the sample covariance of the two.
572+
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the
573+
* given field to calculate the sample covariance of the two.
553574
*
554575
* @param fieldReference must not be {@literal null}.
555576
* @return new instance of {@link CovariancePop}.
@@ -560,8 +581,8 @@ public CovarianceSamp covarianceSamp(String fieldReference) {
560581
}
561582

562583
/**
563-
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given
564-
* {@link AggregationExpression expression} to calculate the sample covariance of the two.
584+
* Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the
585+
* given {@link AggregationExpression expression} to calculate the sample covariance of the two.
565586
*
566587
* @param expression must not be {@literal null}.
567588
* @return new instance of {@link CovariancePop}.
@@ -1798,4 +1819,54 @@ protected String getMongoMethod() {
17981819
return "$derivative";
17991820
}
18001821
}
1822+
1823+
/**
1824+
* Value object to represent an {@link AggregationExpression expression} that calculates the approximation for the
1825+
* mathematical integral value.
1826+
*
1827+
* @author Christoph Strobl
1828+
* @since 3.3
1829+
*/
1830+
public static class Integral extends AbstractAggregationExpression {
1831+
1832+
private Integral(Object value) {
1833+
super(value);
1834+
}
1835+
1836+
/**
1837+
* Create a new instance of {@link Integral} for the value stored at the given field holding a numeric value.
1838+
*
1839+
* @param fieldReference must not be {@literal null}.
1840+
* @return new instance of {@link Integral}.
1841+
*/
1842+
public static Integral integralOf(String fieldReference) {
1843+
return new Integral(Collections.singletonMap("input", Fields.field(fieldReference)));
1844+
}
1845+
1846+
/**
1847+
* Create a new instance of {@link Integral} for the value provided by the given expression that resolves to a
1848+
* numeric value.
1849+
*
1850+
* @param expression must not be {@literal null}.
1851+
* @return new instance of {@link Integral}.
1852+
*/
1853+
public static Integral integralOf(AggregationExpression expression) {
1854+
return new Integral(Collections.singletonMap("input", expression));
1855+
}
1856+
1857+
/**
1858+
* Set the unit of measure.
1859+
*
1860+
* @param unit the unit of measure.
1861+
* @return new instance of {@link Integral}.
1862+
*/
1863+
public Integral unit(String unit) {
1864+
return new Integral(append("unit", unit));
1865+
}
1866+
1867+
@Override
1868+
protected String getMongoMethod() {
1869+
return "$integral";
1870+
}
1871+
}
18011872
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public class MethodReferenceNode extends ExpressionNode {
9292
map.put("trunc", singleArgRef().forOperator("$trunc"));
9393
map.put("round", arrayArgRef().forOperator("$round"));
9494
map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit"));
95+
map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit"));
9596

9697
// STRING OPERATORS
9798
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
@@ -68,4 +68,14 @@ void rendersDerivativeCorrectly() {
6868
valueOf("miles").derivative(SetWindowFieldsOperation.WindowUnits.HOUR).toDocument(Aggregation.DEFAULT_CONTEXT))
6969
.isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }"));
7070
}
71+
72+
@Test // GH-3721
73+
void rendersIntegral() {
74+
assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\" } }"));
75+
}
76+
77+
@Test // GH-3721
78+
void rendersIntegralWithUnit() {
79+
assertThat(valueOf("kilowatts").integral("hour").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }"));
80+
}
7181
}

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

+10
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,16 @@ void shouldRenderDerivative() {
994994
assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }"));
995995
}
996996

997+
@Test // GH-3721
998+
public void shouldRenderIntegral() {
999+
assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}"));
1000+
}
1001+
1002+
@Test // GH-3721
1003+
public void shouldIntegralWithUnit() {
1004+
assertThat(transform("integral(field, 'hour')")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"));
1005+
}
1006+
9971007
private Object transform(String expression, Object... params) {
9981008
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
9991009
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);

0 commit comments

Comments
 (0)