public static AstFilter Translate(TranslationContext context, ParameterExpression expression) { if (expression.Type == typeof(bool)) { if (context.SymbolTable.TryGetSymbol(expression, out var symbol)) { var serializer = context.KnownSerializersRegistry.GetSerializer(expression); var field = AstFilter.Field(symbol.Name, serializer); return(AstFilter.Eq(field, true)); } } throw new ExpressionNotSupportedException(expression); }
// public static methods public static ExecutableQuery <TDocument, bool> Translate <TDocument>(MongoQueryProvider <TDocument> provider, TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Contains)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); IBsonSerializer valueSerializer; if (pipeline.OutputSerializer is IWrappedValueSerializer wrappedValueSerializer) { valueSerializer = wrappedValueSerializer.ValueSerializer; } else { valueSerializer = pipeline.OutputSerializer; wrappedValueSerializer = WrappedValueSerializer.Create("_v", valueSerializer); pipeline = pipeline.AddStages( wrappedValueSerializer, AstStage.Project( AstProject.ExcludeId(), AstProject.Set("_v", AstExpression.Var("ROOT")))); } var itemExpression = arguments[1]; var itemValue = itemExpression.GetConstantValue <object>(containingExpression: expression); var serializedValue = SerializationHelper.SerializeValue(pipeline.OutputSerializer, itemValue); AstFilter filter = AstFilter.Eq(AstFilter.Field("_v", valueSerializer), serializedValue); pipeline = pipeline.AddStages( __outputSerializer, AstStage.Match(filter), AstStage.Limit(1), AstStage.Project( AstProject.ExcludeId(), AstProject.Set("_v", BsonNull.Value))); return(ExecutableQuery.Create( provider.Collection, provider.Options, pipeline, __finalizer)); } throw new ExpressionNotSupportedException(expression); }
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 AstFilter Translate(TranslationContext context, TypeBinaryExpression expression) { if (expression.NodeType == ExpressionType.TypeIs) { var fieldExpression = expression.Expression; var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression); var nominalType = fieldExpression.Type; var actualType = expression.TypeOperand; var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(actualType); var discriminatorField = field.SubField(discriminatorConvention.ElementName, BsonValueSerializer.Instance); var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType); return(AstFilter.Eq(discriminatorField, discriminator)); } throw new ExpressionNotSupportedException(expression); }
private static AstFilter TranslateUsingQueryOperators(TranslationContext context, Expression expression) { switch (expression.NodeType) { case ExpressionType.And: case ExpressionType.AndAlso: return(AndExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression)); case ExpressionType.Call: return(MethodCallExpressionToFilterTranslator.Translate(context, (MethodCallExpression)expression)); case ExpressionType.Equal: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.NotEqual: return(ComparisonExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression)); case ExpressionType.MemberAccess: return(MemberExpressionToFilterTranslator.Translate(context, (MemberExpression)expression)); case ExpressionType.Not: return(NotExpressionToFilterTranslator.Translate(context, (UnaryExpression)expression)); case ExpressionType.Or: case ExpressionType.OrElse: return(OrExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression)); case ExpressionType.Parameter: return(ParameterExpressionToFilterTranslator.Translate(context, (ParameterExpression)expression)); case ExpressionType.TypeIs: return(TypeIsExpressionToFilterTranslator.Translate(context, (TypeBinaryExpression)expression)); } if (expression.Type == typeof(bool)) { var field = ExpressionToFilterFieldTranslator.Translate(context, expression); return(AstFilter.Eq(field, true)); } throw new ExpressionNotSupportedException(expression); }
public static AstFilter Translate(TranslationContext context, MemberExpression expression) { var memberInfo = expression.Member; if (memberInfo is PropertyInfo propertyInfo) { if (propertyInfo.Is(NullableProperty.HasValue)) { var fieldExpression = expression.Expression; var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression); return(AstFilter.Ne(field, BsonNull.Value)); } if (propertyInfo.PropertyType == typeof(bool)) { var field = ExpressionToFilterFieldTranslator.Translate(context, expression); return(AstFilter.Eq(field, true)); } } 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.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); }
private static AstFilter TranslateComparisonToBooleanConstant(TranslationContext context, Expression expression, Expression leftExpression, AstComparisonFilterOperator comparisonOperator, bool comparand) { var filter = ExpressionToFilterTranslator.Translate(context, leftExpression); if (filter is AstFieldOperationFilter fieldOperationFilter && fieldOperationFilter.Operation is AstComparisonFilterOperation comparisonOperation && comparisonOperation.Operator == AstComparisonFilterOperator.Eq && comparisonOperation.Value == true) { var field = fieldOperationFilter.Field; switch (comparisonOperator) { case AstComparisonFilterOperator.Eq: return(AstFilter.Eq(field, comparand)); case AstComparisonFilterOperator.Ne: return(AstFilter.Ne(field, comparand)); default: throw new ExpressionNotSupportedException(expression); } }
private static AstFilter Translate(TranslationContext context, Expression expression, Expression expression1, Expression expression2) { Expression fieldExpression, valueExpression; if (expression1.NodeType == ExpressionType.Constant && expression2.NodeType != ExpressionType.Constant) { (fieldExpression, valueExpression) = (expression2, expression1); } else { (fieldExpression, valueExpression) = (expression1, expression2); } if (StringExpressionToRegexFilterTranslator.TryTranslateComparisonExpression(context, expression, fieldExpression, AstComparisonFilterOperator.Eq, valueExpression, out var filter)) { return(filter); } var field = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression); var value = valueExpression.GetConstantValue <object>(containingExpression: expression); var serializedValue = SerializationHelper.SerializeValue(field.Serializer, value); return(AstFilter.Eq(field, serializedValue)); }