Add support for $expr operator.
Also, allow construction of $match with an AggregationExpression. Closes #3790
This commit is contained in:
@@ -201,4 +201,5 @@ public class AddFieldsOperation extends DocumentEnhancingOperation {
|
||||
AddFieldsOperationBuilder withValueOfExpression(String operation, Object... values);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -498,7 +498,17 @@ public class Aggregation {
|
||||
public static MatchOperation match(CriteriaDefinition criteria) {
|
||||
return new MatchOperation(criteria);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MatchOperation}
|
||||
*
|
||||
* @return new instance of {@link MatchOperation}.
|
||||
* @since 1.10
|
||||
*/
|
||||
public static MatchOperation match() {
|
||||
return new MatchOperation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The
|
||||
* {@code distanceField} defines output field that contains the calculated distance.
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class EvaluationOperators {
|
||||
|
||||
/**
|
||||
* Take the value resulting from the given fieldReference.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link EvaluationOperatorFactory}.
|
||||
*/
|
||||
public static EvaluationOperatorFactory valueOf(String fieldReference) {
|
||||
return new EvaluationOperatorFactory(fieldReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the value resulting from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link EvaluationOperatorFactory}.
|
||||
*/
|
||||
public static EvaluationOperatorFactory valueOf(AggregationExpression expression) {
|
||||
return new EvaluationOperatorFactory(expression);
|
||||
}
|
||||
|
||||
public static class EvaluationOperatorFactory {
|
||||
|
||||
private final String fieldReference;
|
||||
private final AggregationExpression expression;
|
||||
|
||||
/**
|
||||
* Creates new {@link EvaluationOperatorFactory} for given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
*/
|
||||
public EvaluationOperatorFactory(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
this.fieldReference = fieldReference;
|
||||
this.expression = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates new {@link EvaluationOperatorFactory} for given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
*/
|
||||
public EvaluationOperatorFactory(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
this.fieldReference = null;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that is a valid aggregation expression.
|
||||
*
|
||||
* @return new instance of {@link Expr}.
|
||||
*/
|
||||
public Expr expr() {
|
||||
return usesFieldRef() ? Expr.valueOf(fieldReference) : Expr.valueOf(expression);
|
||||
}
|
||||
|
||||
|
||||
public static class Expr extends AbstractAggregationExpression {
|
||||
|
||||
private Expr(Object value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMongoMethod() {
|
||||
return "$expr";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link Expr}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Expr}.
|
||||
*/
|
||||
public static Expr valueOf(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Expr(Fields.field(fieldReference));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link Expr}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Expr}.
|
||||
*/
|
||||
public static Expr valueOf(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Expr(expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean usesFieldRef() {
|
||||
return fieldReference != null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.data.mongodb.core.aggregation.EvaluationOperators.EvaluationOperatorFactory.Expr;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -36,7 +37,16 @@ import org.springframework.util.Assert;
|
||||
public class MatchOperation implements AggregationOperation {
|
||||
|
||||
private final CriteriaDefinition criteriaDefinition;
|
||||
|
||||
private final AggregationExpression expression;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MatchOperation}
|
||||
*/
|
||||
public MatchOperation() {
|
||||
this.criteriaDefinition = null;
|
||||
this.expression = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MatchOperation} for the given {@link CriteriaDefinition}.
|
||||
*
|
||||
@@ -46,14 +56,39 @@ public class MatchOperation implements AggregationOperation {
|
||||
|
||||
Assert.notNull(criteriaDefinition, "Criteria must not be null!");
|
||||
this.criteriaDefinition = criteriaDefinition;
|
||||
this.expression = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link MatchOperation} for the given {@link Expression}.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
*/
|
||||
private MatchOperation(Expr expression) {
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
this.criteriaDefinition = null;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MatchOperation} for the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
*/
|
||||
public MatchOperation withValueOf(AggregationExpression expression) {
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new MatchOperation(EvaluationOperators.valueOf(expression).expr());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public Document toDocument(AggregationOperationContext context) {
|
||||
if(expression != null) {
|
||||
return new Document(getOperator(), expression.toDocument());
|
||||
}
|
||||
return new Document(getOperator(), context.getMappedObject(criteriaDefinition.getCriteriaObject()));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||
import org.springframework.expression.spel.ast.Projection;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -193,5 +193,6 @@ public class SetOperation extends DocumentEnhancingOperation {
|
||||
*/
|
||||
SetOperation withValueOfExpression(String operation, Object... values);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MatchOperationUnitTests {
|
||||
|
||||
@Test // DATAMONGO - 3729
|
||||
public void shouldRenderStdDevPopCorrectly() {
|
||||
MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevPop());
|
||||
assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)).
|
||||
isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevPop\" : \"$quiz\" } } } "));
|
||||
|
||||
}
|
||||
|
||||
@Test // DATAMONGO - 3729
|
||||
public void shouldRenderStdDevSampCorrectly() {
|
||||
MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevSamp());
|
||||
assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)).
|
||||
isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevSamp\" : \"$quiz\" } } } "));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
|
||||
Reference in New Issue
Block a user