public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(EnumerableMethod.Select))
            {
                var sourceExpression            = arguments[0];
                var sourceTranslation           = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var selectorLambda              = (LambdaExpression)arguments[1];
                var selectorParameter           = selectorLambda.Parameters[0];
                var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                var selectorParameterSymbol     = context.CreateSymbol(selectorParameter, selectorParameterSerializer);
                var selectorContext             = context.WithSymbol(selectorParameterSymbol);
                var translatedSelector          = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                var ast = AstExpression.Map(
                    sourceTranslation.Ast,
                    selectorParameterSymbol.Var,
                    translatedSelector.Ast);
                var serializer = IEnumerableSerializer.Create(translatedSelector.Serializer);
                return(new AggregationExpression(expression, ast, serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #2
0
        private static AstPipeline TranslateSelectManyWithCollectionSelectorAndNonIdentityResultSelector(
            TranslationContext context,
            AstPipeline pipeline,
            AggregationExpression collectionSelectorTranslation,
            LambdaExpression resultSelectorLambda)

        {
            var sourceSerializer         = pipeline.OutputSerializer;
            var collectionItemSerializer = ArraySerializerHelper.GetItemSerializer(collectionSelectorTranslation.Serializer);

            var resultSelectorSourceParameterExpression = resultSelectorLambda.Parameters[0];
            var resultSelectorSourceAst                         = AstExpression.Var("ROOT", isCurrent: true);
            var resultSelectorSourceParameterSymbol             = context.CreateSymbol(resultSelectorSourceParameterExpression, resultSelectorSourceAst, sourceSerializer, isCurrent: true);
            var resultSelectorCollectionItemParameterExpression = resultSelectorLambda.Parameters[1];
            var resultSelectorCollectionItemParameterSymbol     = context.CreateSymbol(resultSelectorCollectionItemParameterExpression, collectionItemSerializer);
            var resultSelectorContext        = context.WithSymbols(resultSelectorSourceParameterSymbol, resultSelectorCollectionItemParameterSymbol);
            var resultSelectorTranslation    = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);
            var resultValueSerializer        = resultSelectorTranslation.Serializer;
            var resultWrappedValueSerializer = WrappedValueSerializer.Create("_v", resultValueSerializer);
            var resultAst = AstExpression.Map(
                input: collectionSelectorTranslation.Ast,
                @as: resultSelectorCollectionItemParameterSymbol.Var,
                @in: resultSelectorTranslation.Ast);

            return(pipeline.AddStages(
                       resultWrappedValueSerializer,
                       AstStage.Project(
                           AstProject.Set("_v", resultAst),
                           AstProject.ExcludeId()),
                       AstStage.Unwind("_v")));
        }
Exemple #3
0
        public static AggregationExpression Translate(TranslationContext context, NewExpression expression)
        {
            var listType     = expression.Type;
            var listItemType = listType.GetGenericArguments()[0];
            var arguments    = expression.Arguments;

            if (arguments.Count == 1)
            {
                var argument     = arguments[0];
                var argumentType = argument.Type;
                if (argumentType.IsConstructedGenericType && argumentType.GetGenericTypeDefinition() == typeof(IEnumerable <>))
                {
                    var argumentItemType = argumentType.GetGenericArguments()[0];
                    if (argumentItemType == listItemType)
                    {
                        var collectionExpression  = argument;
                        var collectionTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, collectionExpression);
                        var listSerializerType    = typeof(EnumerableInterfaceImplementerSerializer <,>).MakeGenericType(listType, listItemType);
                        var listItemSerializer    = ArraySerializerHelper.GetItemSerializer(collectionTranslation.Serializer);
                        var listSerializer        = (IBsonSerializer)Activator.CreateInstance(listSerializerType, listItemSerializer);

                        return(new AggregationExpression(expression, collectionTranslation.Ast, listSerializer));
                    }
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #4
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(EnumerableMethod.All))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                var predicateLambda              = (LambdaExpression)arguments[1];
                var predicateParameter           = predicateLambda.Parameters[0];
                var predicateParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                var predicateSymbol              = context.CreateSymbol(predicateParameter, predicateParameterSerializer);
                var predicateContext             = context.WithSymbol(predicateSymbol);
                var predicateTranslation         = ExpressionToAggregationExpressionTranslator.Translate(predicateContext, predicateLambda.Body);

                var ast = AstExpression.AllElementsTrue(
                    AstExpression.Map(
                        input: sourceTranslation.Ast,
                        @as: predicateSymbol.Var,
                        @in: predicateTranslation.Ast));

                return(new AggregationExpression(expression, ast, new BooleanSerializer()));
            }

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

            if (method.IsOneOf(EnumerableMethod.First, EnumerableMethod.FirstWithPredicate, EnumerableMethod.Last, EnumerableMethod.LastWithPredicate))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var array             = sourceTranslation.Ast;
                var itemSerializer    = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                if (method.IsOneOf(EnumerableMethod.FirstWithPredicate, EnumerableMethod.LastWithPredicate))
                {
                    var predicateLambda      = (LambdaExpression)arguments[1];
                    var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, itemSerializer, asRoot: false);
                    var predicateParameter   = predicateLambda.Parameters[0];
                    array = AstExpression.Filter(
                        input: array,
                        cond: predicateTranslation.Ast,
                        @as: predicateParameter.Name);
                }

                var ast = method.Name == "First" ? AstExpression.First(array) : AstExpression.Last(array);
                return(new AggregationExpression(expression, ast, itemSerializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #6
0
        public static AstFilterField Translate(TranslationContext context, BinaryExpression expression)
        {
            if (expression.NodeType == ExpressionType.ArrayIndex)
            {
                var arrayExpression = expression.Left;
                var arrayField      = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression);
                var indexExpression = expression.Right;
                var index           = indexExpression.GetConstantValue <int>(containingExpression: expression);

                if (index < 0)
                {
                    var reason = "negative indexes are not valid";
                    if (index == -1)
                    {
                        reason += ". To use the positional operator $ use FirstMatchingElement instead of an index value of -1"; // closing period is added by exception
                    }
                    throw new ExpressionNotSupportedException(expression, because: reason);
                }

                var itemSerializer = ArraySerializerHelper.GetItemSerializer(arrayField.Serializer);
                return(arrayField.SubField(index.ToString(), itemSerializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AstFilter Translate(TranslationContext context, Expression arrayFieldExpression, ConstantExpression arrayConstantExpression)
        {
            var arrayFieldTranslation = ExpressionToFilterFieldTranslator.Translate(context, arrayFieldExpression);
            var itemSerializer        = ArraySerializerHelper.GetItemSerializer(arrayFieldTranslation.Serializer);
            var values           = (IEnumerable)arrayConstantExpression.Value;
            var serializedValues = SerializationHelper.SerializeValues(itemSerializer, values);

            return(AstFilter.In(arrayFieldTranslation, serializedValues));
        }
Exemple #8
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__averageMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                AstExpression ast;
                if (method.IsOneOf(__averageWithSelectorMethods))
                {
                    var selectorLambda       = (LambdaExpression)arguments[1];
                    var selectorParameter    = selectorLambda.Parameters[0];
                    var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var selectorSymbol       = context.CreateSymbol(selectorParameter, sourceItemSerializer);
                    var selectorContext      = context.WithSymbol(selectorSymbol);
                    var selectorTranslation  = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);

                    ast = AstExpression.Avg(
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorSymbol.Var,
                            @in: selectorTranslation.Ast));
                }
                else
                {
                    ast = AstExpression.Avg(sourceTranslation.Ast);
                }
                IBsonSerializer serializer = expression.Type switch
                {
                    Type t when t == typeof(int) => new Int32Serializer(),
                    Type t when t == typeof(long) => new Int64Serializer(),
                    Type t when t == typeof(float) => new SingleSerializer(),
                    Type t when t == typeof(double) => new DoubleSerializer(),
                    Type t when t == typeof(decimal) => new DecimalSerializer(),
                    Type {
                        IsConstructedGenericType : true
                    } t when t.GetGenericTypeDefinition() == typeof(Nullable <>) => (IBsonSerializer)Activator.CreateInstance(typeof(NullableSerializer <>).MakeGenericType(t.GenericTypeArguments[0])),
                    _ => throw new ExpressionNotSupportedException(expression)
                };

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
    }
Exemple #9
0
        public static AstFilter Translate(TranslationContext context, MethodCallExpression expression)
        {
            if (AllWithContainsInPredicateMethodToFilterTranslator.CanTranslate(expression, out var arrayFieldExpression, out var arrayConstantExpression))
            {
                return(AllWithContainsInPredicateMethodToFilterTranslator.Translate(context, arrayFieldExpression, arrayConstantExpression));
            }

            if (AnyWithContainsInPredicateMethodToFilterTranslator.CanTranslate(expression, out arrayFieldExpression, out arrayConstantExpression))
            {
                return(AnyWithContainsInPredicateMethodToFilterTranslator.Translate(context, arrayFieldExpression, arrayConstantExpression));
            }

            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(EnumerableMethod.All, EnumerableMethod.Any, EnumerableMethod.AnyWithPredicate))
            {
                var sourceExpression = arguments[0];
                var(field, filter) = FilteredEnumerableFilterFieldTranslator.Translate(context, sourceExpression);

                if (method.IsOneOf(EnumerableMethod.All, EnumerableMethod.AnyWithPredicate))
                {
                    var predicateLambda     = (LambdaExpression)arguments[1];
                    var parameterExpression = predicateLambda.Parameters.Single();
                    var elementSerializer   = ArraySerializerHelper.GetItemSerializer(field.Serializer);
                    var parameterSymbol     = context.CreateSymbol(parameterExpression, "@<elem>", elementSerializer); // @<elem> represents the implied element
                    var predicateContext    = context.WithSingleSymbol(parameterSymbol);                               // @<elem> is the only symbol visible inside an $elemMatch
                    var predicateFilter     = ExpressionToFilterTranslator.Translate(predicateContext, predicateLambda.Body, exprOk: false);

                    filter = AstFilter.Combine(filter, predicateFilter);
                }

                if (method.Is(EnumerableMethod.All))
                {
                    return(AstFilter.Not(AstFilter.ElemMatch(field, AstFilter.Not(filter))));
                }
                else
                {
                    if (filter == null)
                    {
                        return(AstFilter.And(AstFilter.Ne(field, BsonNull.Value), AstFilter.Not(AstFilter.Size(field, 0))));
                    }
                    else
                    {
                        return(AstFilter.ElemMatch(field, filter));
                    }
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AstFilterField Translate(TranslationContext context, BinaryExpression expression)
        {
            if (expression.NodeType == ExpressionType.ArrayIndex)
            {
                var arrayExpression = expression.Left;
                var arrayField      = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression);
                var indexExpression = expression.Right;
                var index           = indexExpression.GetConstantValue <int>(containingExpression: expression);
                var itemSerializer  = ArraySerializerHelper.GetItemSerializer(arrayField.Serializer);
                return(arrayField.SubField(index.ToString(), itemSerializer));
            }

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

            if (method.IsOneOf(__countMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                AstExpression ast;
                if (method.IsOneOf(__countWithPredicateMethods))
                {
                    if (sourceExpression.Type == typeof(string))
                    {
                        throw new ExpressionNotSupportedException(expression);
                    }

                    var predicateLambda      = (LambdaExpression)arguments[1];
                    var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, sourceItemSerializer, asRoot: false);
                    var filteredSourceAst    = AstExpression.Filter(
                        input: sourceTranslation.Ast,
                        cond: predicateTranslation.Ast,
                        @as: predicateLambda.Parameters[0].Name);
                    ast = AstExpression.Size(filteredSourceAst);
                }
                else
                {
                    if (sourceExpression.Type == typeof(string))
                    {
                        ast = AstExpression.StrLenCP(sourceTranslation.Ast);
                    }
                    else
                    {
                        ast = AstExpression.Size(sourceTranslation.Ast);
                    }
                }
                var serializer = GetSerializer(expression.Type);

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, BinaryExpression expression)
        {
            if (expression.NodeType == ExpressionType.ArrayIndex)
            {
                var arrayExpression  = expression.Left;
                var arrayTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, arrayExpression);
                var indexExpression  = expression.Right;
                var indexTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, indexExpression);
                var ast            = AstExpression.ArrayElemAt(arrayTranslation.Ast, indexTranslation.Ast);
                var itemSerializer = ArraySerializerHelper.GetItemSerializer(arrayTranslation.Serializer);
                return(new AggregationExpression(expression, ast, itemSerializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #13
0
        private static AstPipeline TranslateSelectManyWithCollectionSelectorAndIdentityResultSelector(
            AstPipeline pipeline,
            AggregationExpression collectionSelectorTranslation)
        {
            var collectionItemSerializer     = ArraySerializerHelper.GetItemSerializer(collectionSelectorTranslation.Serializer);
            var resultValueSerializer        = collectionItemSerializer;
            var resultWrappedValueSerializer = WrappedValueSerializer.Create("_v", resultValueSerializer);

            return(pipeline.AddStages(
                       resultWrappedValueSerializer,
                       AstStage.Project(
                           AstProject.Set("_v", collectionSelectorTranslation.Ast),
                           AstProject.ExcludeId()),
                       AstStage.Unwind("_v")));
        }
Exemple #14
0
        public static (AstFilterField, AstFilter) Translate(TranslationContext context, Expression sourceExpression)
        {
            if (sourceExpression is MethodCallExpression sourceMethodCallExpression)
            {
                var method    = sourceMethodCallExpression.Method;
                var arguments = sourceMethodCallExpression.Arguments;

                if (method.Is(EnumerableMethod.OfType))
                {
                    var ofTypeSourceExpression = arguments[0];
                    var(sourceField, sourceFilter) = Translate(context, ofTypeSourceExpression);

                    var nominalType                    = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer).ValueType;
                    var actualType                     = method.GetGenericArguments()[0];
                    var discriminatorConvention        = BsonSerializer.LookupDiscriminatorConvention(actualType);
                    var discriminatorField             = AstFilter.Field(discriminatorConvention.ElementName, BsonValueSerializer.Instance);
                    var discriminatorValue             = discriminatorConvention.GetDiscriminator(nominalType, actualType);
                    var ofTypeFilter                   = AstFilter.Eq(discriminatorField, discriminatorValue);
                    var actualTypeSerializer           = context.KnownSerializersRegistry.GetSerializer(sourceExpression);
                    var enumerableActualTypeSerializer = IEnumerableSerializer.Create(actualTypeSerializer);
                    var actualTypeSourceField          = AstFilter.Field(sourceField.Path, enumerableActualTypeSerializer);
                    var combinedFilter                 = AstFilter.Combine(sourceFilter, ofTypeFilter);

                    return(actualTypeSourceField, combinedFilter);
                }

                if (method.Is(EnumerableMethod.Where))
                {
                    var whereSourceExpression = arguments[0];
                    var(sourceField, sourceFilter) = Translate(context, whereSourceExpression);

                    var predicateLambda     = (LambdaExpression)arguments[1];
                    var parameterExpression = predicateLambda.Parameters.Single();
                    var itemSerializer      = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer);
                    var parameterSymbol     = context.CreateSymbol(parameterExpression, "@<elem>", itemSerializer); // @<elem> represents the implied element
                    var predicateContext    = context.WithSingleSymbol(parameterSymbol);                            // @<elem> is the only symbol visible inside an $elemMatch
                    var whereFilter         = ExpressionToFilterTranslator.Translate(predicateContext, predicateLambda.Body, exprOk: false);
                    var combinedFilter      = AstFilter.Combine(sourceFilter, whereFilter);

                    return(sourceField, combinedFilter);
                }
            }

            var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression);

            return(field, null);
        }
Exemple #15
0
        private static AstFilter Translate(TranslationContext context, Expression expression, Expression sourceExpression, Expression itemExpression)
        {
            if (itemExpression.NodeType == ExpressionType.Constant)
            {
                var sourceField     = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression);
                var itemSerializer  = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer);
                var value           = itemExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedValue = SerializationHelper.SerializeValue(itemSerializer, value);
                return(AstFilter.ElemMatch(sourceField, AstFilter.Eq(AstFilter.Field("@<elem>", itemSerializer), serializedValue))); // @<elem> represents the implied element
            }

            var itemField        = ExpressionToFilterFieldTranslator.Translate(context, itemExpression);
            var sourceValues     = sourceExpression.GetConstantValue <IEnumerable>(containingExpression: expression);
            var serializedValues = SerializationHelper.SerializeValues(itemField.Serializer, sourceValues);

            return(AstFilter.In(itemField, serializedValues));
        }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(EnumerableMethod.Reverse))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var ast            = AstExpression.ReverseArray(sourceTranslation.Ast);
                var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                var serializer     = IEnumerableSerializer.Create(itemSerializer);
                return(new AggregationExpression(expression, ast, serializer));
            }

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

            if (method.Is(EnumerableMethod.ToArray))
            {
                var sourceExpression    = arguments[0];
                var sourceTranslation   = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var arrayItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                var arrayItemType       = arrayItemSerializer.ValueType;
                var arraySerializerType = typeof(ArraySerializer <>).MakeGenericType(arrayItemType);
                var arraySerializer     = (IBsonSerializer)Activator.CreateInstance(arraySerializerType, arrayItemSerializer);
                return(new AggregationExpression(expression, sourceTranslation.Ast, arraySerializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #18
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__sumMethods))
            {
                var sourceExpression     = arguments[0];
                var sourceTranslation    = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                AstExpression   ast;
                IBsonSerializer serializer;
                if (arguments.Count == 1)
                {
                    ast        = AstExpression.Sum(sourceTranslation.Ast);
                    serializer = sourceItemSerializer;
                }
                else
                {
                    var selectorLambda      = (LambdaExpression)arguments[1];
                    var selectorParameter   = selectorLambda.Parameters[0];
                    var selectorSymbol      = context.CreateSymbol(selectorParameter, sourceItemSerializer);
                    var selectorContext     = context.WithSymbol(selectorSymbol);
                    var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                    ast = AstExpression.Sum(
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorSymbol.Var,
                            @in: selectorTranslation.Ast));
                    serializer = selectorTranslation.Serializer;
                }

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

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

            if (method.DeclaringType == typeof(Enumerable) && (method.Name == "Max" || method.Name == "Min"))
            {
                var             sourceExpression  = arguments[0];
                var             sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                AstExpression   ast;
                IBsonSerializer serializer;
                if (arguments.Count == 1)
                {
                    var array = sourceTranslation.Ast;
                    ast        = method.Name == "Max" ? AstExpression.Max(array) : AstExpression.Min(array);
                    serializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                }
                else
                {
                    var selectorLambda              = (LambdaExpression)arguments[1];
                    var selectorParameter           = selectorLambda.Parameters[0];
                    var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var selectorParameterSymbol     = context.CreateSymbol(selectorParameter, selectorParameterSerializer);
                    var selectorContext             = context.WithSymbol(selectorParameterSymbol);
                    var selectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                    var mappedArray =
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorParameterSymbol.Var,
                            @in: selectorTranslation.Ast);
                    ast        = method.Name == "Max" ? AstExpression.Max(mappedArray) : AstExpression.Min(mappedArray);
                    serializer = selectorTranslation.Serializer;
                }
                return(new AggregationExpression(expression, ast, serializer));
            }

            if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #20
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            Expression sourceExpression, indexExpression, keyExpression;

            if (IsBsonValueGetItemMethodWithIntIndex(expression, out sourceExpression, out indexExpression))
            {
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var indexTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, indexExpression);
                var ast             = AstExpression.ArrayElemAt(sourceTranslation.Ast, indexTranslation.Ast);
                var valueSerializer = BsonValueSerializer.Instance;
                return(new AggregationExpression(expression, ast, valueSerializer));
            }

            if (IsBsonValueGetItemMethodWithStringKey(expression, out sourceExpression, out keyExpression))
            {
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var keyTranslation    = ExpressionToAggregationExpressionTranslator.Translate(context, keyExpression);
                var ast             = AstExpression.GetField(sourceTranslation.Ast, keyTranslation.Ast);
                var valueSerializer = BsonValueSerializer.Instance;
                return(new AggregationExpression(expression, ast, valueSerializer));
            }

            if (IsEnumerableGetItemMethodWithIntIndex(expression, out sourceExpression, out indexExpression))
            {
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var indexTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, indexExpression);
                var ast        = AstExpression.ArrayElemAt(sourceTranslation.Ast, indexTranslation.Ast);
                var serializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                return(new AggregationExpression(expression, ast, serializer));
            }

            if (IsDictionaryGetItemMethodWithStringKey(expression, out sourceExpression, out keyExpression))
            {
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var key             = keyExpression.GetConstantValue <string>(containingExpression: expression);
                var ast             = AstExpression.GetField(sourceTranslation.Ast, key); // TODO: verify that dictionary is using Document representation
                var valueSerializer = GetDictionaryValueSerializer(sourceTranslation.Serializer);
                return(new AggregationExpression(expression, ast, valueSerializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #21
0
        private static AstPipeline TranslateSelectMany(
            TranslationContext context,
            AstPipeline pipeline,
            ReadOnlyCollection <Expression> arguments)
        {
            var sourceSerializer             = pipeline.OutputSerializer;
            var selectorLambda               = ExpressionHelper.UnquoteLambda(arguments[1]);
            var selectorTranslation          = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true);
            var resultValueSerializer        = ArraySerializerHelper.GetItemSerializer(selectorTranslation.Serializer);
            var resultWrappedValueSerializer = WrappedValueSerializer.Create("_v", resultValueSerializer);

            pipeline = pipeline.AddStages(
                resultWrappedValueSerializer,
                AstStage.Project(
                    AstProject.Set("_v", selectorTranslation.Ast),
                    AstProject.ExcludeId()),
                AstStage.Unwind("_v"));

            return(pipeline);
        }
Exemple #22
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (IsStandardDeviationMethod(method, out var stddevOperator))
            {
                if (arguments.Count == 1 || arguments.Count == 2)
                {
                    var sourceExpression  = arguments[0];
                    var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                    if (arguments.Count == 2)
                    {
                        var selectorLambda              = (LambdaExpression)arguments[1];
                        var selectorParameter           = selectorLambda.Parameters[0];
                        var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                        var selectorParameterSymbol     = context.CreateSymbol(selectorParameter, selectorParameterSerializer);
                        var selectorContext             = context.WithSymbol(selectorParameterSymbol);
                        var selectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                        var selectorAst = AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorParameterSymbol.Var,
                            @in: selectorTranslation.Ast);
                        var selectorResultSerializer = BsonSerializer.LookupSerializer(selectorLambda.ReturnType);
                        sourceTranslation = new AggregationExpression(selectorLambda, selectorAst, selectorResultSerializer);
                    }

                    var ast        = AstExpression.StdDev(stddevOperator, sourceTranslation.Ast);
                    var serializer = BsonSerializer.LookupSerializer(expression.Type);
                    return(new AggregationExpression(expression, ast, serializer));
                }
            }

            if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #23
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(EnumerableMethod.DefaultIfEmpty, EnumerableMethod.DefaultIfEmptyWithDefaultValue))
            {
                var           sourceExpression  = arguments[0];
                var           sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var           sourceVar         = AstExpression.Var("source");
                var           sourceVarBinding  = AstExpression.VarBinding(sourceVar, sourceTranslation.Ast);
                AstExpression defaultValueAst;
                if (method.Is(EnumerableMethod.DefaultIfEmpty))
                {
                    var sourceItemSerializer   = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var defaultValue           = Activator.CreateInstance(sourceItemSerializer.ValueType);
                    var serializedDefaultValue = SerializationHelper.SerializeValue(sourceItemSerializer, defaultValue);
                    defaultValueAst = AstExpression.Constant(new BsonArray {
                        serializedDefaultValue
                    });
                }
                else
                {
                    var defaultValueExpression  = arguments[1];
                    var defaultValueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, defaultValueExpression);
                    defaultValueAst = AstExpression.ComputedArray(new[] { defaultValueTranslation.Ast });
                }
                var ast = AstExpression.Let(
                    sourceVarBinding,
                    AstExpression.Cond(
                        AstExpression.Eq(AstExpression.Size(sourceVar), 0),
                        defaultValueAst,
                        sourceVar));
                return(new AggregationExpression(expression, ast, sourceTranslation.Serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #24
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(EnumerableMethod.Take))
            {
                var        sourceExpression = arguments[0];
                var        countExpression  = arguments[1];
                Expression skipExpression   = null;
                if (sourceExpression is MethodCallExpression sourceSkipExpression && sourceSkipExpression.Method.Is(EnumerableMethod.Skip))
                {
                    sourceExpression = sourceSkipExpression.Arguments[0];
                    skipExpression   = sourceSkipExpression.Arguments[1];
                }

                var           sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, sourceExpression);
                var           countTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, countExpression);
                AstExpression ast;
                if (skipExpression == null)
                {
                    ast = AstExpression.Slice(sourceTranslation.Ast, countTranslation.Ast);
                }
                else
                {
                    var skipTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, skipExpression);
                    ast = AstExpression.Slice(sourceTranslation.Ast, skipTranslation.Ast, countTranslation.Ast);
                }
                var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                var serializer     = IEnumerableSerializer.Create(itemSerializer);

                return(new AggregationExpression(expression, ast, serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #25
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(EnumerableMethod.Where, MongoEnumerableMethod.WhereWithLimit))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var itemSerializer    = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                var predicateLambda      = (LambdaExpression)arguments[1];
                var predicateParameter   = predicateLambda.Parameters[0];
                var predicateSymbol      = context.CreateSymbol(predicateParameter, itemSerializer);
                var predicateContext     = context.WithSymbol(predicateSymbol);
                var predicateTranslation = ExpressionToAggregationExpressionTranslator.Translate(predicateContext, predicateLambda.Body);

                AggregationExpression limitTranslation = null;
                if (method.Is(MongoEnumerableMethod.WhereWithLimit))
                {
                    var limitExpression = arguments[2];
                    limitTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, limitExpression);
                }

                var ast = AstExpression.Filter(
                    sourceTranslation.Ast,
                    predicateTranslation.Ast,
                    predicateParameter.Name,
                    limitTranslation?.Ast);

                var enumerableSerializer = IEnumerableSerializer.Create(itemSerializer);
                return(new AggregationExpression(expression, ast, enumerableSerializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemple #26
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__aggregateMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var itemSerializer    = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                if (method.Is(EnumerableMethod.AggregateWithFunc))
                {
                    var funcLambda           = (LambdaExpression)arguments[1];
                    var funcParameters       = funcLambda.Parameters;
                    var accumulatorParameter = funcParameters[0];
                    var accumulatorSymbol    = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", itemSerializer); // note: MQL uses $$value for the accumulator
                    var itemParameter        = funcParameters[1];
                    var itemSymbol           = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer);         // note: MQL uses $$this for the item being processed
                    var funcContext          = context.WithSymbols(accumulatorSymbol, itemSymbol);
                    var funcTranslation      = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body);

                    var sourceVar = AstExpression.Var("source");
                    var ast       = AstExpression.Let(
                        var: AstExpression.VarBinding(sourceVar, sourceTranslation.Ast),
                        @in: AstExpression.Cond(
                            @if: AstExpression.Lte(AstExpression.Size(sourceVar), 1),
                            @then: AstExpression.ArrayElemAt(sourceVar, 0),
                            @else: AstExpression.Reduce(
                                input: AstExpression.Slice(sourceVar, 1, int.MaxValue),
                                initialValue: AstExpression.ArrayElemAt(sourceVar, 0),
                                @in: funcTranslation.Ast)));

                    return(new AggregationExpression(expression, ast, itemSerializer));
                }
                else if (method.IsOneOf(EnumerableMethod.AggregateWithSeedAndFunc, EnumerableMethod.AggregateWithSeedFuncAndResultSelector))
                {
                    var seedExpression  = arguments[1];
                    var seedTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, seedExpression);

                    var funcLambda            = (LambdaExpression)arguments[2];
                    var funcParameters        = funcLambda.Parameters;
                    var accumulatorParameter  = funcParameters[0];
                    var accumulatorSerializer = context.KnownSerializersRegistry.GetSerializer(accumulatorParameter);
                    var accumulatorSymbol     = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", accumulatorSerializer); // note: MQL uses $$value for the accumulator
                    var itemParameter         = funcParameters[1];
                    var itemSymbol            = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer);                // note: MQL uses $$this for the item being processed
                    var funcContext           = context.WithSymbols(accumulatorSymbol, itemSymbol);
                    var funcTranslation       = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body);

                    var ast = AstExpression.Reduce(
                        input: sourceTranslation.Ast,
                        initialValue: seedTranslation.Ast,
                        @in: funcTranslation.Ast);
                    var serializer = accumulatorSerializer;

                    if (method.Is(EnumerableMethod.AggregateWithSeedFuncAndResultSelector))
                    {
                        var resultSelectorLambda              = (LambdaExpression)arguments[3];
                        var resultSelectorParameter           = resultSelectorLambda.Parameters[0];
                        var resultSelectorParameterSerializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorParameter);
                        var resultSelectorSymbol              = context.CreateSymbol(resultSelectorParameter, resultSelectorParameterSerializer);
                        var resultSelectorContext             = context.WithSymbol(resultSelectorSymbol);
                        var resultSelectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);

                        ast = AstExpression.Let(
                            var: AstExpression.VarBinding(resultSelectorSymbol.Var, ast),
                            @in: resultSelectorTranslation.Ast);
                        serializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorLambda);
                    }

                    return(new AggregationExpression(expression, ast, serializer));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }