// 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.All)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var predicateLambda = ExpressionHelper.UnquoteLambda(arguments[1]); var predicateFilter = ExpressionToFilterTranslator.TranslateLambda(context, predicateLambda, parameterSerializer: pipeline.OutputSerializer); pipeline = pipeline.AddStages( __outputSerializer, AstStage.Match(AstFilter.Not(predicateFilter)), 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); }
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 methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Join)) { var outerExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, outerExpression); var outerSerializer = pipeline.OutputSerializer; var wrapOuterStage = AstStage.Project( AstProject.Set("_outer", AstExpression.Var("ROOT")), AstProject.ExcludeId()); var wrappedOuterSerializer = WrappedValueSerializer.Create("_outer", outerSerializer); var innerExpression = arguments[1]; var(innerCollectionName, innerSerializer) = innerExpression.GetCollectionInfo(containerExpression: expression); var outerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[2]); var localFieldPath = outerKeySelectorLambda.GetFieldPath(context, wrappedOuterSerializer); var innerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[3]); var foreignFieldPath = innerKeySelectorLambda.GetFieldPath(context, innerSerializer); var lookupStage = AstStage.Lookup( from: innerCollectionName, match: new AstLookupStageEqualityMatch(localFieldPath, foreignFieldPath), @as: "_inner"); var unwindStage = AstStage.Unwind("_inner"); var resultSelectorLambda = ExpressionHelper.UnquoteLambda(arguments[4]); var root = AstExpression.Var("ROOT", isCurrent: true); var outerParameter = resultSelectorLambda.Parameters[0]; var outerField = AstExpression.GetField(root, "_outer"); var outerSymbol = context.CreateSymbol(outerParameter, outerField, outerSerializer); var innerParameter = resultSelectorLambda.Parameters[1]; var innerField = AstExpression.GetField(root, "_inner"); var innerSymbol = context.CreateSymbol(innerParameter, innerField, innerSerializer); var resultSelectorContext = context.WithSymbols(outerSymbol, innerSymbol); var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body); var(projectStage, newOutputSerializer) = ProjectionHelper.CreateProjectStage(resultSelectorTranslation); pipeline = pipeline.AddStages( newOutputSerializer, wrapOuterStage, lookupStage, unwindStage, projectStage); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
private static (AstProjectStage, IBsonSerializer) CreateWrappedValueProjectStage(AggregationExpression expression) { var wrappedValueSerializer = WrappedValueSerializer.Create("_v", expression.Serializer); var projectStage = AstStage.Project( AstProject.Set("_v", expression.Ast), AstProject.ExcludeId()); return(projectStage, wrappedValueSerializer); }
// private static methods private static (AstProjectStage, IBsonSerializer) CreateComputedDocumentProjectStage(AggregationExpression expression) { var computedDocument = (AstComputedDocumentExpression)expression.Ast; var specifications = new List <AstProjectStageSpecification>(); var isIdProjected = false; foreach (var computedField in computedDocument.Fields) { var path = computedField.Path; var value = computedField.Value; if (value is AstConstantExpression astConstantExpression) { if (ValueNeedsToBeQuoted(astConstantExpression.Value)) { value = AstExpression.Literal(value); } } specifications.Add(AstProject.Set(path, value)); isIdProjected |= path == "_id"; } if (!isIdProjected) { specifications.Add(AstProject.ExcludeId()); } var projectStage = AstStage.Project(specifications); return(projectStage, expression.Serializer); bool ValueNeedsToBeQuoted(BsonValue constantValue) { switch (constantValue.BsonType) { case BsonType.Boolean: case BsonType.Decimal128: case BsonType.Double: case BsonType.Int32: case BsonType.Int64: return(true); default: return(false); } } }
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 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); }
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); }