Пример #1
0
        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);
Пример #2
0
            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));
            }
Пример #3
0
            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);
                }
            }