private AstPipeline OptimizeGroupStage(AstPipeline pipeline, int i, AstGroupStage groupStage) { try { if (IsOptimizableGroupStage(groupStage)) { var followingStages = GetFollowingStagesToOptimize(pipeline, i + 1); if (followingStages == null) { return(pipeline); } var mappings = OptimizeGroupAndFollowingStages(groupStage, followingStages); if (mappings.Length > 0) { return((AstPipeline)AstNodeReplacer.Replace(pipeline, mappings)); } } } catch (UnableToRemoveReferenceToElementsException) { // wasn't able to optimize away all references to _elements } return(pipeline);
public override AstNode VisitMapExpression(AstMapExpression node) { // { $map : { input : { $getField : { input : "$$ROOT", field : "_elements" } }, as : "x", in : f(x) } } => { __agg0 : { $push : f(x => root) } } + "$__agg0" if (node.Input is AstGetFieldExpression mapInputGetFieldExpression && mapInputGetFieldExpression.FieldName is AstConstantExpression mapInputconstantFieldExpression && mapInputconstantFieldExpression.Value.IsString && mapInputconstantFieldExpression.Value.AsString == "_elements" && mapInputGetFieldExpression.Input is AstVarExpression mapInputGetFieldVarExpression && mapInputGetFieldVarExpression.Name == "ROOT") { var root = AstExpression.Var("ROOT", isCurrent: true); var rewrittenArg = (AstExpression)AstNodeReplacer.Replace(node.In, (node.As, root)); var accumulatorExpression = AstExpression.AccumulatorExpression(AstAccumulatorOperator.Push, rewrittenArg); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); return(AstExpression.GetField(root, accumulatorFieldName)); } return(base.VisitMapExpression(node)); }
public override AstNode VisitUnaryExpression(AstUnaryExpression node) { var root = AstExpression.Var("ROOT", isCurrent: true); if (TryOptimizeSizeOfElements(out var optimizedExpression)) { return(optimizedExpression); } if (TryOptimizeAccumulatorOfElements(out optimizedExpression)) { return(optimizedExpression); } if (TryOptimizeAccumulatorOfMappedElements(out optimizedExpression)) { return(optimizedExpression); } return(base.VisitUnaryExpression(node)); bool TryOptimizeSizeOfElements(out AstExpression optimizedExpression) { // { $size : "$_elements" } => { __agg0 : { $sum : 1 } } + "$__agg0" if (node.Operator == AstUnaryOperator.Size) { if (node.Arg is AstGetFieldExpression argGetFieldExpression && argGetFieldExpression.FieldName is AstConstantExpression constantFieldNameExpression && constantFieldNameExpression.Value.IsString && constantFieldNameExpression.Value.AsString == "_elements") { var accumulatorExpression = AstExpression.AccumulatorExpression(AstAccumulatorOperator.Sum, 1); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); return(true); } } optimizedExpression = null; return(false); } bool TryOptimizeAccumulatorOfElements(out AstExpression optimizedExpression) { // { $accumulator : { $getField : { input : "$$ROOT", field : "_elements" } } } => { __agg0 : { $accumulator : "$$ROOT" } } + "$__agg0" if (node.Operator.IsAccumulator(out var accumulatorOperator) && node.Arg is AstGetFieldExpression getFieldExpression && getFieldExpression.FieldName is AstConstantExpression getFieldConstantFieldNameExpression && getFieldConstantFieldNameExpression.Value.IsString && getFieldConstantFieldNameExpression.Value == "_elements" && getFieldExpression.Input is AstVarExpression getFieldInputVarExpression && getFieldInputVarExpression.Name == "ROOT") { var accumulatorExpression = AstExpression.AccumulatorExpression(accumulatorOperator, root); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); return(true); } optimizedExpression = null; return(false); } bool TryOptimizeAccumulatorOfMappedElements(out AstExpression optimizedExpression) { // { $accumulator : { $map : { input : { $getField : { input : "$$ROOT", field : "_elements" } }, as : "x", in : f(x) } } } => { __agg0 : { $accumulator : f(x => root) } } + "$__agg0" if (node.Operator.IsAccumulator(out var accumulatorOperator) && node.Arg is AstMapExpression mapExpression && mapExpression.Input is AstGetFieldExpression mapInputGetFieldExpression && mapInputGetFieldExpression.FieldName is AstConstantExpression mapInputconstantFieldExpression && mapInputconstantFieldExpression.Value.IsString && mapInputconstantFieldExpression.Value.AsString == "_elements" && mapInputGetFieldExpression.Input is AstVarExpression mapInputGetFieldVarExpression && mapInputGetFieldVarExpression.Name == "ROOT") { var rewrittenArg = (AstExpression)AstNodeReplacer.Replace(mapExpression.In, (mapExpression.As, root)); var accumulatorExpression = AstExpression.AccumulatorExpression(accumulatorOperator, rewrittenArg); var accumulatorFieldName = _accumulators.AddAccumulatorExpression(accumulatorExpression); optimizedExpression = AstExpression.GetField(root, accumulatorFieldName); return(true); } optimizedExpression = null; return(false); } }