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); }
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"))); }
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); }
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); }
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)); }
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); } }
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); }
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"))); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }