Skip to content

Commit 2a3a4cf

Browse files
committed
Polishing.
Fix method order from earlier merges. Add missing Javadoc. Simplify tests. Update documentation. See #3721 Original pull request: #3746.
1 parent df2b2a2 commit 2a3a4cf

File tree

4 files changed

+109
-73
lines changed

4 files changed

+109
-73
lines changed

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

+78-40
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,46 @@ public Ceil ceil() {
155155
return usesFieldRef() ? Ceil.ceilValueOf(fieldReference) : Ceil.ceilValueOf(expression);
156156
}
157157

158+
/**
159+
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
160+
*
161+
* @return new instance of {@link Derivative}.
162+
* @since 3.3
163+
*/
164+
public Derivative derivative() {
165+
return derivative((String) null);
166+
}
167+
168+
/**
169+
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
170+
*
171+
* @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR},
172+
* {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply.
173+
* @return new instance of {@link Derivative}.
174+
* @since 3.3
175+
*/
176+
public Derivative derivative(WindowUnit unit) {
177+
178+
Assert.notNull(unit, "Window unit must not be null");
179+
180+
return derivative(unit.name().toLowerCase(Locale.ROOT));
181+
}
182+
183+
/**
184+
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
185+
*
186+
* @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be
187+
* {@literal null}.
188+
* @return new instance of {@link Derivative}.
189+
* @since 3.3
190+
*/
191+
public Derivative derivative(@Nullable String unit) {
192+
193+
Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference)
194+
: Derivative.derivativeOf(expression);
195+
return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative;
196+
}
197+
158198
/**
159199
* Creates new {@link AggregationExpression} that ivides the associated number by number referenced via
160200
* {@literal fieldReference}.
@@ -226,6 +266,21 @@ public Integral integral() {
226266
return usesFieldRef() ? Integral.integralOf(fieldReference) : Integral.integralOf(expression);
227267
}
228268

269+
/**
270+
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
271+
*
272+
* @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR},
273+
* {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply.
274+
* @return new instance of {@link Derivative}.
275+
* @since 3.3
276+
*/
277+
public Integral integral(WindowUnit unit) {
278+
279+
Assert.notNull(unit, "Window unit must not be null");
280+
281+
return integral(unit.name().toLowerCase(Locale.ROOT));
282+
}
283+
229284
/**
230285
* Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value.
231286
*
@@ -234,6 +289,9 @@ public Integral integral() {
234289
* @since 3.3
235290
*/
236291
public Integral integral(String unit) {
292+
293+
Assert.hasText(unit, "Unit must not be empty!");
294+
237295
return integral().unit(unit);
238296
}
239297

@@ -618,46 +676,6 @@ public Round roundToPlace(int place) {
618676
return round().place(place);
619677
}
620678

621-
/**
622-
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
623-
*
624-
* @return new instance of {@link Derivative}.
625-
* @since 3.3
626-
*/
627-
public Derivative derivative() {
628-
return derivative((String) null);
629-
}
630-
631-
/**
632-
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
633-
*
634-
* @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR},
635-
* {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply.
636-
* @return new instance of {@link Derivative}.
637-
* @since 3.3
638-
*/
639-
public Derivative derivative(WindowUnit unit) {
640-
641-
Assert.notNull(unit, "Window unit must not be null");
642-
643-
return derivative(unit.name().toLowerCase(Locale.ROOT));
644-
}
645-
646-
/**
647-
* Creates new {@link AggregationExpression} that calculates the mathematical derivative value.
648-
*
649-
* @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be
650-
* {@literal null}.
651-
* @return new instance of {@link Derivative}.
652-
* @since 3.3
653-
*/
654-
public Derivative derivative(@Nullable String unit) {
655-
656-
Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference)
657-
: Derivative.derivativeOf(expression);
658-
return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative;
659-
}
660-
661679
private boolean usesFieldRef() {
662680
return fieldReference != null;
663681
}
@@ -1792,16 +1810,36 @@ protected String getMongoMethod() {
17921810
}
17931811
}
17941812

1813+
/**
1814+
* Value object to represent an {@link AggregationExpression expression} that calculates the average rate of change
1815+
* within the specified window.
1816+
*
1817+
* @author Christoph Strobl
1818+
* @since 3.3
1819+
*/
17951820
public static class Derivative extends AbstractAggregationExpression {
17961821

17971822
private Derivative(Object value) {
17981823
super(value);
17991824
}
18001825

1826+
/**
1827+
* Create a new instance of {@link Derivative} for the value stored at the given field holding a numeric value.
1828+
*
1829+
* @param fieldReference must not be {@literal null}.
1830+
* @return new instance of {@link Derivative}.
1831+
*/
18011832
public static Derivative derivativeOf(String fieldReference) {
18021833
return new Derivative(Collections.singletonMap("input", Fields.field(fieldReference)));
18031834
}
18041835

1836+
/**
1837+
* Create a new instance of {@link Derivative} for the value provided by the given expression that resolves to a
1838+
* numeric value.
1839+
*
1840+
* @param expression must not be {@literal null}.
1841+
* @return new instance of {@link Derivative}.
1842+
*/
18051843
public static Derivative derivativeOf(AggregationExpression expression) {
18061844
return new Derivative(Collections.singletonMap("input", expression));
18071845
}

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
*/
1616
package org.springframework.data.mongodb.core.aggregation;
1717

18-
import static org.assertj.core.api.Assertions.*;
1918
import static org.springframework.data.mongodb.core.aggregation.ArithmeticOperators.*;
19+
import static org.springframework.data.mongodb.test.util.Assertions.*;
2020

2121
import java.util.Arrays;
2222
import java.util.Collections;
@@ -66,16 +66,19 @@ void rendersDerivativeCorrectly() {
6666

6767
assertThat(
6868
valueOf("miles").derivative(SetWindowFieldsOperation.WindowUnits.HOUR).toDocument(Aggregation.DEFAULT_CONTEXT))
69-
.isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }"));
69+
.isEqualTo("{ $derivative: { input: \"$miles\", unit: \"hour\" } }");
7070
}
7171

7272
@Test // GH-3721
7373
void rendersIntegral() {
74-
assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\" } }"));
74+
assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT))
75+
.isEqualTo("{ $integral : { input : \"$kilowatts\" } }");
7576
}
7677

7778
@Test // GH-3721
7879
void rendersIntegralWithUnit() {
79-
assertThat(valueOf("kilowatts").integral("hour").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }"));
80+
assertThat(valueOf("kilowatts").integral(SetWindowFieldsOperation.WindowUnits.HOUR)
81+
.toDocument(Aggregation.DEFAULT_CONTEXT))
82+
.isEqualTo("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }");
8083
}
8184
}

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

+23-28
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import org.junit.jupiter.api.BeforeEach;
2424
import org.junit.jupiter.api.Disabled;
2525
import org.junit.jupiter.api.Test;
26+
2627
import org.springframework.data.mongodb.core.Person;
27-
import org.springframework.lang.Nullable;
2828

2929
/**
3030
* Unit tests for {@link SpelExpressionTransformer}.
@@ -152,8 +152,8 @@ void shouldRenderBinaryExpressionWithMixedSignsCorrectly() {
152152
@Test // DATAMONGO-774
153153
void shouldRenderConsecutiveOperationsInComplexExpression() {
154154

155-
assertThat(transform("1 + 1 + (1 + 1 + 1) / q")).isEqualTo(
156-
Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}"));
155+
assertThat(transform("1 + 1 + (1 + 1 + 1) / q"))
156+
.isEqualTo(Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}"));
157157
}
158158

159159
@Test // DATAMONGO-774
@@ -189,8 +189,7 @@ void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() {
189189

190190
Person person = new Person();
191191
person.setAge(10);
192-
assertThat(transform("[0].age + a.c", person))
193-
.isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }"));
192+
assertThat(transform("[0].age + a.c", person)).isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }"));
194193
}
195194

196195
@Test // DATAMONGO-840
@@ -216,8 +215,7 @@ void shouldRenderMethodReferenceNodeNot() {
216215

217216
@Test // DATAMONGO-1530
218217
void shouldRenderMethodReferenceNodeSetEquals() {
219-
assertThat(transform("setEquals(a, b)"))
220-
.isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}"));
218+
assertThat(transform("setEquals(a, b)")).isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}"));
221219
}
222220

223221
@Test // DATAMONGO-1530
@@ -379,8 +377,7 @@ void shouldRenderMethodReferenceTrunc() {
379377

380378
@Test // DATAMONGO-1530
381379
void shouldRenderMethodReferenceNodeConcat() {
382-
assertThat(transform("concat(a, b, 'c')"))
383-
.isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}"));
380+
assertThat(transform("concat(a, b, 'c')")).isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}"));
384381
}
385382

386383
@Test // DATAMONGO-1530
@@ -400,8 +397,7 @@ void shouldRenderMethodReferenceToUpper() {
400397

401398
@Test // DATAMONGO-1530
402399
void shouldRenderMethodReferenceNodeStrCaseCmp() {
403-
assertThat(transform("strcasecmp(a, b)"))
404-
.isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}"));
400+
assertThat(transform("strcasecmp(a, b)")).isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}"));
405401
}
406402

407403
@Test // DATAMONGO-1530
@@ -411,8 +407,7 @@ void shouldRenderMethodReferenceMeta() {
411407

412408
@Test // DATAMONGO-1530
413409
void shouldRenderMethodReferenceNodeArrayElemAt() {
414-
assertThat(transform("arrayElemAt(a, 10)"))
415-
.isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}"));
410+
assertThat(transform("arrayElemAt(a, 10)")).isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}"));
416411
}
417412

418413
@Test // DATAMONGO-1530
@@ -511,15 +506,14 @@ void shouldRenderMethodReferenceMillisecond() {
511506

512507
@Test // DATAMONGO-1530
513508
void shouldRenderMethodReferenceDateToString() {
514-
assertThat(transform("dateToString('%Y-%m-%d', $date)")).isEqualTo(
515-
Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}"));
509+
assertThat(transform("dateToString('%Y-%m-%d', $date)"))
510+
.isEqualTo(Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}"));
516511
}
517512

518513
@Test // DATAMONGO-1530
519514
void shouldRenderMethodReferenceCond() {
520515
assertThat(transform("cond(qty > 250, 30, 20)")).isEqualTo(
521-
Document
522-
.parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}"));
516+
Document.parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}"));
523517
}
524518

525519
@Test // DATAMONGO-1530
@@ -633,8 +627,7 @@ void shouldRenderOperationNodeAnd() {
633627
@Test // DATAMONGO-1530
634628
void shouldRenderComplexOperationNodeAnd() {
635629
assertThat(transform("1+2 && concat(a, b) && true")).isEqualTo(
636-
Document
637-
.parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}"));
630+
Document.parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}"));
638631
}
639632

640633
@Test // DATAMONGO-1530
@@ -644,8 +637,7 @@ void shouldRenderNotCorrectly() {
644637

645638
@Test // DATAMONGO-1530
646639
void shouldRenderComplexNotCorrectly() {
647-
assertThat(transform("!(foo > 10)"))
648-
.isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}"));
640+
assertThat(transform("!(foo > 10)")).isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}"));
649641
}
650642

651643
@Test // DATAMONGO-1548
@@ -951,12 +943,14 @@ void shouldRenderRoundWithPlace() {
951943

952944
@Test // GH-3712
953945
void shouldRenderCovariancePop() {
954-
assertThat(transform("covariancePop(field1, field2)")).isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}"));
946+
assertThat(transform("covariancePop(field1, field2)"))
947+
.isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}"));
955948
}
956949

957950
@Test // GH-3712
958951
void shouldRenderCovarianceSamp() {
959-
assertThat(transform("covarianceSamp(field1, field2)")).isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}"));
952+
assertThat(transform("covarianceSamp(field1, field2)"))
953+
.isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}"));
960954
}
961955

962956
@Test // GH-3715
@@ -988,20 +982,21 @@ void rendersShiftWithDefault() {
988982
.isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }"));
989983
}
990984

991-
@Nullable
992985
@Test // GH-3716
993986
void shouldRenderDerivative() {
994-
assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }"));
987+
assertThat(transform("derivative(miles, 'hour')"))
988+
.isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }"));
995989
}
996990

997991
@Test // GH-3721
998-
public void shouldRenderIntegral() {
992+
void shouldRenderIntegral() {
999993
assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}"));
1000994
}
1001995

1002996
@Test // GH-3721
1003-
public void shouldIntegralWithUnit() {
1004-
assertThat(transform("integral(field, 'hour')")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"));
997+
void shouldRenderIntegralWithUnit() {
998+
assertThat(transform("integral(field, 'hour')"))
999+
.isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"));
10051000
}
10061001

10071002
private Object transform(String expression, Object... params) {

src/main/asciidoc/reference/aggregation-framework.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op
8585
| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp`
8686

8787
| Arithmetic Aggregation Operators
88-
| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc`
88+
| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc`
8989

9090
| String Aggregation Operators
9191
| `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim`

0 commit comments

Comments
 (0)