示例#1
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(QueryableMethod.OrderBy, QueryableMethod.OrderByDescending, QueryableMethod.ThenBy, QueryableMethod.ThenByDescending))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                var keySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                var sortField         = CreateSortField(context, method.Name, keySelectorLambda, parameterSerializer: pipeline.OutputSerializer);
                switch (method.Name)
                {
                case "OrderBy":
                case "OrderByDescending":
                    pipeline = pipeline.AddStages(pipeline.OutputSerializer, AstStage.Sort(sortField));
                    break;

                case "ThenBy":
                case "ThenByDescending":
                    var oldSortStage = (AstSortStage)pipeline.Stages.Last();
                    var newSortStage = oldSortStage.AddSortField(sortField);
                    pipeline = pipeline.ReplaceLastStage(pipeline.OutputSerializer, newSortStage);
                    break;
                }

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Select))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                var selectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                if (selectorLambda.Body == selectorLambda.Parameters[0])
                {
                    return(pipeline); // ignore identity projection: Select(x => x)
                }

                var selectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true);
                var(projectStage, projectionSerializer) = ProjectionHelper.CreateProjectStage(selectorTranslation);
                pipeline = pipeline.AddStages(projectionSerializer, projectStage);

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__groupByMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                var keySelectorLambda      = ExpressionHelper.UnquoteLambda(arguments[1]);
                var keySelectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, keySelectorLambda, sourceSerializer, asRoot: true);
                var keySerializer          = keySelectorTranslation.Serializer;

                var(elementAst, elementSerializer) = TranslateElement(context, method, arguments, sourceSerializer);

                var groupingSerializer = IGroupingSerializer.Create(keySerializer, elementSerializer);
                pipeline = pipeline.AddStages(
                    groupingSerializer,
                    AstStage.Group(
                        id: keySelectorTranslation.Ast,
                        fields: AstExpression.AccumulatorField("_elements", AstAccumulatorOperator.Push, elementAst)));

                if (method.IsOneOf(__groupByWithResultSelectorMethods))
                {
                    pipeline = TranslateResultSelector(context, pipeline, arguments, keySerializer, elementSerializer);
                }

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Join))
            {
                var outerExpression = arguments[0];
                var pipeline        = ExpressionToPipelineTranslator.Translate(context, outerExpression);
                var outerSerializer = pipeline.OutputSerializer;

                var wrapOuterStage = AstStage.Project(
                    AstProject.Set("_outer", AstExpression.Var("ROOT")),
                    AstProject.ExcludeId());
                var wrappedOuterSerializer = WrappedValueSerializer.Create("_outer", outerSerializer);

                var innerExpression = arguments[1];
                var(innerCollectionName, innerSerializer) = innerExpression.GetCollectionInfo(containerExpression: expression);

                var outerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[2]);
                var localFieldPath         = outerKeySelectorLambda.GetFieldPath(context, wrappedOuterSerializer);

                var innerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[3]);
                var foreignFieldPath       = innerKeySelectorLambda.GetFieldPath(context, innerSerializer);

                var lookupStage = AstStage.Lookup(
                    from: innerCollectionName,
                    match: new AstLookupStageEqualityMatch(localFieldPath, foreignFieldPath),
                    @as: "_inner");

                var unwindStage = AstStage.Unwind("_inner");

                var resultSelectorLambda = ExpressionHelper.UnquoteLambda(arguments[4]);
                var root                      = AstExpression.Var("ROOT", isCurrent: true);
                var outerParameter            = resultSelectorLambda.Parameters[0];
                var outerField                = AstExpression.GetField(root, "_outer");
                var outerSymbol               = context.CreateSymbol(outerParameter, outerField, outerSerializer);
                var innerParameter            = resultSelectorLambda.Parameters[1];
                var innerField                = AstExpression.GetField(root, "_inner");
                var innerSymbol               = context.CreateSymbol(innerParameter, innerField, innerSerializer);
                var resultSelectorContext     = context.WithSymbols(outerSymbol, innerSymbol);
                var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);
                var(projectStage, newOutputSerializer) = ProjectionHelper.CreateProjectStage(resultSelectorTranslation);

                pipeline = pipeline.AddStages(
                    newOutputSerializer,
                    wrapOuterStage,
                    lookupStage,
                    unwindStage,
                    projectStage);

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(MongoQueryableMethod.DensifyWithArrayPartitionByFields))
            {
                var sourceExpression = ConvertHelper.RemoveConvertToMongoQueryable(arguments[0]);
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                var fieldLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                var fieldPath   = fieldLambda.GetFieldPath(context, sourceSerializer);

                var rangeExpression = arguments[2];
                var range           = rangeExpression.GetConstantValue <DensifyRange>(expression);

                List <string> partitionByFieldPaths;
                var           partitionByFieldExpressions = arguments[3];
                if (partitionByFieldExpressions is NewArrayExpression newArrayExpression)
                {
                    partitionByFieldPaths = new List <string>();
                    foreach (var partitionByFieldExpression in newArrayExpression.Expressions)
                    {
                        var partitionByFieldLambda = ExpressionHelper.UnquoteLambda(partitionByFieldExpression);
                        var partitionByFieldPath   = partitionByFieldLambda.GetFieldPath(context, sourceSerializer);
                        partitionByFieldPaths.Add(partitionByFieldPath);
                    }
                }
                else if (
                    partitionByFieldExpressions is ConstantExpression constantExpression &&
                    constantExpression.Value == null)
                {
                    partitionByFieldPaths = null;
                }
                else
                {
                    throw new ExpressionNotSupportedException(partitionByFieldExpressions, expression);
                }

                var stage = AstStage.Densify(fieldPath, range, partitionByFieldPaths);

                pipeline = pipeline.AddStages(sourceSerializer, stage);
                return(pipeline);
            }
示例#6
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Distinct))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var rootVar          = AstExpression.Var("ROOT", isCurrent: true);

                pipeline = pipeline.AddStages(
                    pipeline.OutputSerializer,
                    AstStage.Group(rootVar, Enumerable.Empty <AstAccumulatorField>()),
                    AstStage.ReplaceRoot(AstExpression.GetField(rootVar, "_id")));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Where))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                var predicateLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                var predicateFilter = ExpressionToFilterTranslator.TranslateLambda(context, predicateLambda, parameterSerializer: pipeline.OutputSerializer);

                pipeline = pipeline.AddStages(
                    pipeline.OutputSerializer,
                    AstStage.Match(predicateFilter));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
示例#8
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Take))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                var countExpression = arguments[1];
                var count           = countExpression.GetConstantValue <int>(containingExpression: expression);

                pipeline = pipeline.AddStages(
                    pipeline.OutputSerializer,
                    AstStage.Limit(count));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
示例#9
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(MongoQueryableMethod.Sample))
            {
                var sourceExpression = ConvertHelper.RemoveConvertToMongoQueryable(arguments[0]);
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                var sizeExpression = arguments[1];
                var size           = sizeExpression.GetConstantValue <long>(containingExpression: expression);

                pipeline = pipeline.AddStages(
                    pipeline.OutputSerializer,
                    AstStage.Sample(size));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
示例#10
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.OfType))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                var sourceType                   = sourceExpression.Type;
                var nominalType                  = sourceType.GetGenericArguments()[0];
                var actualType                   = method.GetGenericArguments()[0];
                var discriminatorConvention      = BsonSerializer.LookupDiscriminatorConvention(nominalType);
                var discriminatorElementName     = discriminatorConvention.ElementName;
                var wrappedValueOutputSerializer = pipeline.OutputSerializer as IWrappedValueSerializer;
                if (wrappedValueOutputSerializer != null)
                {
                    discriminatorElementName = wrappedValueOutputSerializer.FieldName + "." + discriminatorElementName;
                }
                var discriminatorField = AstFilter.Field(discriminatorElementName, BsonValueSerializer.Instance);
                var discriminatorValue = discriminatorConvention.GetDiscriminator(nominalType, actualType);
                var filter             = AstFilter.Eq(discriminatorField, discriminatorValue); // note: OfType only works with hierarchical discriminators
                var actualSerializer   = context.KnownSerializersRegistry.GetSerializer(expression);
                if (wrappedValueOutputSerializer != null)
                {
                    actualSerializer = WrappedValueSerializer.Create(wrappedValueOutputSerializer.FieldName, actualSerializer);
                }

                pipeline = pipeline.AddStages(
                    actualSerializer,
                    AstStage.Match(filter));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
示例#11
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__selectManyMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                if (method.Is(QueryableMethod.SelectMany))
                {
                    return(TranslateSelectMany(context, pipeline, arguments));
                }

                if (method.Is(QueryableMethod.SelectManyWithCollectionSelectorAndResultSelector))
                {
                    return(TranslateSelectManyWithCollectionSelectorAndResultSelector(context, pipeline, arguments));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }