Accept expression as input for filter aggregation operator.
Closes #4394 Original pull request: #4395
This commit is contained in:
committed by
Mark Paluch
parent
110877eb04
commit
048af85be0
@@ -79,7 +79,7 @@ public class ArrayOperators {
|
|||||||
|
|
||||||
private final @Nullable String fieldReference;
|
private final @Nullable String fieldReference;
|
||||||
private final @Nullable AggregationExpression expression;
|
private final @Nullable AggregationExpression expression;
|
||||||
private final @Nullable Collection values;
|
private final @Nullable Collection<?> values;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new {@link ArrayOperatorFactory} for given {@literal fieldReference}.
|
* Creates new {@link ArrayOperatorFactory} for given {@literal fieldReference}.
|
||||||
@@ -214,6 +214,10 @@ public class ArrayOperators {
|
|||||||
return Filter.filter(fieldReference);
|
return Filter.filter(fieldReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usesExpression()) {
|
||||||
|
return Filter.filter(expression);
|
||||||
|
}
|
||||||
|
|
||||||
Assert.state(values != null, "Values must not be null");
|
Assert.state(values != null, "Values must not be null");
|
||||||
return Filter.filter(new ArrayList<>(values));
|
return Filter.filter(new ArrayList<>(values));
|
||||||
}
|
}
|
||||||
@@ -317,7 +321,8 @@ public class ArrayOperators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new {@link AggregationExpression} that takes the associated array and sorts it by the given {@link Sort order}.
|
* Creates new {@link AggregationExpression} that takes the associated array and sorts it by the given {@link Sort
|
||||||
|
* order}.
|
||||||
*
|
*
|
||||||
* @return new instance of {@link SortArray}.
|
* @return new instance of {@link SortArray}.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
@@ -397,8 +402,8 @@ public class ArrayOperators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new {@link AggregationExpression} that return the last element in the given array.
|
* Creates new {@link AggregationExpression} that return the last element in the given array. <strong>NOTE:</strong>
|
||||||
* <strong>NOTE:</strong> Requires MongoDB 4.4 or later.
|
* Requires MongoDB 4.4 or later.
|
||||||
*
|
*
|
||||||
* @return new instance of {@link Last}.
|
* @return new instance of {@link Last}.
|
||||||
* @since 3.4
|
* @since 3.4
|
||||||
@@ -649,6 +654,19 @@ public class ArrayOperators {
|
|||||||
return new FilterExpressionBuilder().filter(field);
|
return new FilterExpressionBuilder().filter(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link AggregationExpression} resolving to an arry to apply the {@code $filter} to.
|
||||||
|
*
|
||||||
|
* @param expression must not be {@literal null}.
|
||||||
|
* @return never {@literal null}.
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
public static AsBuilder filter(AggregationExpression expression) {
|
||||||
|
|
||||||
|
Assert.notNull(expression, "Field must not be null");
|
||||||
|
return new FilterExpressionBuilder().filter(expression);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the {@literal values} to apply the {@code $filter} to.
|
* Set the {@literal values} to apply the {@code $filter} to.
|
||||||
*
|
*
|
||||||
@@ -681,7 +699,16 @@ public class ArrayOperators {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object getMappedInput(AggregationOperationContext context) {
|
private Object getMappedInput(AggregationOperationContext context) {
|
||||||
return input instanceof Field field ? context.getReference(field).toString() : input;
|
|
||||||
|
if (input instanceof Field field) {
|
||||||
|
return context.getReference(field).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input instanceof AggregationExpression expression) {
|
||||||
|
return expression.toDocument(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getMappedCondition(AggregationOperationContext context) {
|
private Object getMappedCondition(AggregationOperationContext context) {
|
||||||
@@ -715,6 +742,15 @@ public class ArrayOperators {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
AsBuilder filter(Field field);
|
AsBuilder filter(Field field);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link AggregationExpression} resolving to an array to apply the {@code $filter} to.
|
||||||
|
*
|
||||||
|
* @param expression must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
* @since 4.1.1
|
||||||
|
*/
|
||||||
|
AsBuilder filter(AggregationExpression expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -797,6 +833,14 @@ public class ArrayOperators {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AsBuilder filter(AggregationExpression expression) {
|
||||||
|
|
||||||
|
Assert.notNull(expression, "Expression must not be null");
|
||||||
|
filter.input = expression;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConditionBuilder as(String variableName) {
|
public ConditionBuilder as(String variableName) {
|
||||||
|
|
||||||
@@ -1333,7 +1377,7 @@ public class ArrayOperators {
|
|||||||
Assert.notNull(expressions, "PropertyExpressions must not be null");
|
Assert.notNull(expressions, "PropertyExpressions must not be null");
|
||||||
|
|
||||||
return new Reduce(Fields.field(fieldReference), initialValue,
|
return new Reduce(Fields.field(fieldReference), initialValue,
|
||||||
Arrays.<AggregationExpression>asList(expressions));
|
Arrays.<AggregationExpression> asList(expressions));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1690,7 +1734,7 @@ public class ArrayOperators {
|
|||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Shashank Sharma
|
* @author Shashank Sharma
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/in/">https://docs.mongodb.com/manual/reference/operator/aggregation/in/</a>
|
* "https://docs.mongodb.com/manual/reference/operator/aggregation/in/">https://docs.mongodb.com/manual/reference/operator/aggregation/in/</a>
|
||||||
* @since 2.2
|
* @since 2.2
|
||||||
*/
|
*/
|
||||||
public static class In extends AbstractAggregationExpression {
|
public static class In extends AbstractAggregationExpression {
|
||||||
@@ -1779,7 +1823,7 @@ public class ArrayOperators {
|
|||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/">https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/</a>
|
* "https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/">https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/</a>
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public static class ArrayToObject extends AbstractAggregationExpression {
|
public static class ArrayToObject extends AbstractAggregationExpression {
|
||||||
|
|||||||
@@ -117,6 +117,23 @@ class FilterExpressionUnitTests {
|
|||||||
assertThat($filter).isEqualTo(new Document(expected));
|
assertThat($filter).isEqualTo(new Document(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // GH-4394
|
||||||
|
void filterShouldAcceptExpression() {
|
||||||
|
|
||||||
|
Document $filter = ArrayOperators.arrayOf(ObjectOperators.valueOf("data.metadata").toArray()).filter().as("item")
|
||||||
|
.by(ComparisonOperators.valueOf("item.price").greaterThan("field-1")).toDocument(Aggregation.DEFAULT_CONTEXT);
|
||||||
|
|
||||||
|
Document expected = Document.parse("""
|
||||||
|
{ $filter : {
|
||||||
|
input: { $objectToArray: "$data.metadata" },
|
||||||
|
as: "item",
|
||||||
|
cond: { $gt: [ "$$item.price", "$field-1" ] }
|
||||||
|
}}
|
||||||
|
""");
|
||||||
|
|
||||||
|
assertThat($filter).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
private Document extractFilterOperatorFromDocument(Document source) {
|
private Document extractFilterOperatorFromDocument(Document source) {
|
||||||
|
|
||||||
List<Object> pipeline = DocumentTestUtils.getAsDBList(source, "pipeline");
|
List<Object> pipeline = DocumentTestUtils.getAsDBList(source, "pipeline");
|
||||||
|
|||||||
Reference in New Issue
Block a user