Skip to content

Commit 9217821

Browse files
christophstroblmp911de
authored andcommitted
Add support for $locf aggregation operator.
See #4139 Original pull request: #4182.
1 parent 8d223ab commit 9217821

File tree

4 files changed

+67
-1
lines changed

4 files changed

+67
-1
lines changed

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

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
package org.springframework.data.mongodb.core.aggregation;
1717

1818
import org.bson.Document;
19-
2019
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
2120
import org.springframework.util.Assert;
2221

2322
/**
2423
* Gateway to {@literal evaluation operators} such as {@literal $expr}.
2524
*
2625
* @author Divya Srivastava
26+
* @author Christoph Strobl
2727
* @since 3.3
2828
*/
2929
public class EvaluationOperators {
@@ -86,6 +86,15 @@ public Expr expr() {
8686
return usesFieldRef() ? Expr.valueOf(fieldReference) : Expr.valueOf(expression);
8787
}
8888

89+
/**
90+
* Creates new {@link AggregationExpression} that is a valid aggregation expression.
91+
*
92+
* @return new instance of {@link Expr}.
93+
*/
94+
public LastObservationCarriedForward locf() {
95+
return usesFieldRef() ? LastObservationCarriedForward.locfValueOf(fieldReference) : LastObservationCarriedForward.locfValueOf(expression);
96+
}
97+
8998
/**
9099
* Allows the use of aggregation expressions within the query language.
91100
*/
@@ -152,4 +161,45 @@ private boolean usesFieldRef() {
152161
}
153162
}
154163

164+
/**
165+
* Sets {@literal null} and missing values to the last non-null value.
166+
*
167+
* @since 4.0
168+
*/
169+
public static class LastObservationCarriedForward extends AbstractAggregationExpression {
170+
171+
private LastObservationCarriedForward(Object value) {
172+
super(value);
173+
}
174+
175+
@Override
176+
protected String getMongoMethod() {
177+
return "$locf";
178+
}
179+
180+
/**
181+
* Creates new {@link EvaluationOperatorFactory.Expr}.
182+
*
183+
* @param fieldReference must not be {@literal null}.
184+
* @return new instance of {@link EvaluationOperatorFactory.Expr}.
185+
*/
186+
public static LastObservationCarriedForward locfValueOf(String fieldReference) {
187+
188+
Assert.notNull(fieldReference, "FieldReference must not be null");
189+
return new LastObservationCarriedForward(Fields.field(fieldReference));
190+
}
191+
192+
/**
193+
* Creates new {@link LastObservationCarriedForward}.
194+
*
195+
* @param expression must not be {@literal null}.
196+
* @return new instance of {@link LastObservationCarriedForward}.
197+
*/
198+
public static LastObservationCarriedForward locfValueOf(AggregationExpression expression) {
199+
200+
Assert.notNull(expression, "Expression must not be null");
201+
return new LastObservationCarriedForward(expression);
202+
}
203+
}
204+
155205
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ public class MethodReferenceNode extends ExpressionNode {
251251
map.put("toString", singleArgRef().forOperator("$toString"));
252252
map.put("degreesToRadians", singleArgRef().forOperator("$degreesToRadians"));
253253

254+
// expression operators
255+
map.put("locf", singleArgRef().forOperator("$locf"));
256+
254257
FUNCTIONS = Collections.unmodifiableMap(map);
255258
}
256259

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* Unit tests for {@link EvaluationOperators}.
2424
*
2525
* @author Mark Paluch
26+
* @author Christoph Strobl
2627
*/
2728
class EvaluationOperatorsUnitTests {
2829

@@ -32,4 +33,11 @@ void shouldRenderExprCorrectly() {
3233
assertThat(EvaluationOperators.valueOf("foo").expr().toDocument(Aggregation.DEFAULT_CONTEXT))
3334
.isEqualTo("{ $expr: \"$foo\" }");
3435
}
36+
37+
@Test // GH-4139
38+
void shouldRenderLocfCorrectly() {
39+
40+
assertThat(EvaluationOperators.valueOf("foo").locf().toDocument(Aggregation.DEFAULT_CONTEXT))
41+
.isEqualTo("{ $locf: \"$foo\" }");
42+
}
3543
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,11 @@ void shouldTsIncrement() {
12501250
void shouldTsSecond() {
12511251
assertThat(transform("tsSecond(saleTimestamp)")).isEqualTo("{ $tsSecond: \"$saleTimestamp\" }");
12521252
}
1253+
1254+
@Test // GH-4139
1255+
void shouldRenderLocf() {
1256+
assertThat(transform("locf(price)")).isEqualTo("{ $locf: \"$price\" }");
1257+
}
12531258

12541259
private Document transform(String expression, Object... params) {
12551260
return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);

0 commit comments

Comments
 (0)