-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CSHARP-5436: Optimize special case of Any with constant array and fie… #1585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,53 @@ static bool OperatorMapsNullToNull(AstUnaryOperator @operator) | |
} | ||
} | ||
|
||
public override AstNode VisitExprFilter(AstExprFilter node) | ||
{ | ||
var optimizedNode = base.VisitExprFilter(node); | ||
|
||
if (optimizedNode is AstExprFilter exprFilter && | ||
exprFilter.Expression is AstUnaryExpression unaryExpression && | ||
unaryExpression.Operator == AstUnaryOperator.AnyElementTrue && | ||
unaryExpression.Arg is AstMapExpression mapExpression && | ||
mapExpression.Input is AstConstantExpression inputConstant && | ||
inputConstant.Value is BsonArray inputArrayValue && | ||
mapExpression.In is AstBinaryExpression inBinaryExpression && | ||
inBinaryExpression.Operator == AstBinaryOperator.Eq && | ||
TryGetBinaryExpressionArguments(inBinaryExpression, out AstFieldPathExpression fieldPathExpression, out AstVarExpression varExpression) && | ||
fieldPathExpression.Path.Length > 1 && fieldPathExpression.Path[0] == '$' && fieldPathExpression.Path[1] != '$' && | ||
varExpression == mapExpression.As) | ||
{ | ||
// { $expr : { $anyElementTrue : { $map : { input : <constantArray>, as : "<var>", in : { $eq : ["$<dottedFieldName>", "$$<var>"] } } } } } | ||
// => { "<dottedFieldName>" : { $in : <constantArray> } } | ||
return AstFilter.In(AstFilter.Field(fieldPathExpression.Path.Substring(1)), inputArrayValue); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment just before this line to visualize the simplification being done:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
|
||
return optimizedNode; | ||
|
||
static bool TryGetBinaryExpressionArguments<T1, T2>(AstBinaryExpression binaryExpression, out T1 arg1, out T2 arg2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Theoretically could be reusable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can wait until there is a need. |
||
where T1 : AstNode | ||
where T2 : AstNode | ||
{ | ||
if (binaryExpression.Arg1 is T1 arg1AsT1 && binaryExpression.Arg2 is T2 arg2AsT2) | ||
{ | ||
arg1 = arg1AsT1; | ||
arg2 = arg2AsT2; | ||
return true; | ||
} | ||
|
||
if (binaryExpression.Arg1 is T2 arg1AsT2 && binaryExpression.Arg1 is T1 arg2AsT1) | ||
{ | ||
arg1 = arg2AsT1; | ||
arg2 = arg1AsT2; | ||
return true; | ||
} | ||
|
||
arg1 = null; | ||
arg2 = null; | ||
return false; | ||
} | ||
} | ||
|
||
public override AstNode VisitFieldOperationFilter(AstFieldOperationFilter node) | ||
{ | ||
node = (AstFieldOperationFilter)base.VisitFieldOperationFilter(node); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have some more elegant way to check if fieldPath points to the "current" variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean.
But anything that starts with
$$
is not a field so I think that's all we need to check.