1616using MongoDB . Bson ;
1717using MongoDB . Driver . Linq . Linq3Implementation . Ast . Expressions ;
1818using MongoDB . Driver . Linq . Linq3Implementation . Ast . Filters ;
19- using MongoDB . Driver . Linq . Linq3Implementation . Ast . Stages ;
2019using MongoDB . Driver . Linq . Linq3Implementation . Ast . Visitors ;
2120
2221namespace MongoDB . Driver . Linq . Linq3Implementation . Ast . Optimizers
@@ -37,6 +36,48 @@ public static TNode SimplifyAndConvert<TNode>(TNode node)
3736 }
3837 #endregion
3938
39+ public override AstNode VisitCondExpression ( AstCondExpression node )
40+ {
41+ // { $cond : [{ $eq : [expr1, null] }, null, expr2] }
42+ if ( node . If is AstBinaryExpression binaryIfpression &&
43+ binaryIfpression . Operator == AstBinaryOperator . Eq &&
44+ binaryIfpression . Arg1 is AstExpression expr1 &&
45+ binaryIfpression . Arg2 is AstConstantExpression constantComparandExpression &&
46+ constantComparandExpression . Value == BsonNull . Value &&
47+ node . Then is AstConstantExpression constantThenExpression &&
48+ constantThenExpression . Value == BsonNull . Value &&
49+ node . Else is AstExpression expr2 )
50+ {
51+ // { $cond : [{ $eq : [expr, null] }, null, expr] } => expr
52+ if ( expr1 == expr2 )
53+ {
54+ return Visit ( expr2 ) ;
55+ }
56+
57+ // { $cond : [{ $eq : [expr, null] }, null, { $toT : expr }] } => { $toT : expr } for operators that map null to null
58+ if ( expr2 is AstUnaryExpression unaryElseExpression &&
59+ OperatorMapsNullToNull ( unaryElseExpression . Operator ) &&
60+ unaryElseExpression . Arg == expr1 )
61+ {
62+ return Visit ( expr2 ) ;
63+ }
64+ }
65+
66+ return base . VisitCondExpression ( node ) ;
67+
68+ static bool OperatorMapsNullToNull ( AstUnaryOperator @operator )
69+ {
70+ return @operator switch
71+ {
72+ AstUnaryOperator . ToDecimal => true ,
73+ AstUnaryOperator . ToDouble => true ,
74+ AstUnaryOperator . ToInt => true ,
75+ AstUnaryOperator . ToLong => true ,
76+ _ => false
77+ } ;
78+ }
79+ }
80+
4081 public override AstNode VisitFieldOperationFilter ( AstFieldOperationFilter node )
4182 {
4283 node = ( AstFieldOperationFilter ) base . VisitFieldOperationFilter ( node ) ;
@@ -281,6 +322,22 @@ bool TrySimplifyAsLet(AstGetFieldExpression node, out AstExpression simplified)
281322 }
282323 }
283324
325+ public override AstNode VisitLetExpression ( AstLetExpression node )
326+ {
327+ node = ( AstLetExpression ) base . VisitLetExpression ( node ) ;
328+
329+ // { $let : { vars : { var : expr }, in : "$$var" } } => expr
330+ if ( node . Vars . Count == 1 &&
331+ node . Vars [ 0 ] . Var . Name is string varName &&
332+ node . In is AstVarExpression varExpression &&
333+ varExpression . Name == varName )
334+ {
335+ return node . Vars [ 0 ] . Value ;
336+ }
337+
338+ return node ;
339+ }
340+
284341 public override AstNode VisitMapExpression ( AstMapExpression node )
285342 {
286343 // { $map : { input : <input>, as : "v", in : "$$v.x" } } => { $getField : { field : "x", input : <input> } }
0 commit comments