// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(QueryableMethod.OrderBy, QueryableMethod.OrderByDescending, QueryableMethod.ThenBy, QueryableMethod.ThenByDescending)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var keySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]); var sortField = CreateSortField(context, method.Name, keySelectorLambda, parameterSerializer: pipeline.OutputSerializer); switch (method.Name) { case "OrderBy": case "OrderByDescending": pipeline = pipeline.AddStages(pipeline.OutputSerializer, AstStage.Sort(sortField)); break; case "ThenBy": case "ThenByDescending": var oldSortStage = (AstSortStage)pipeline.Stages.Last(); var newSortStage = oldSortStage.AddSortField(sortField); pipeline = pipeline.ReplaceLastStage(pipeline.OutputSerializer, newSortStage); break; } return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Select)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var sourceSerializer = pipeline.OutputSerializer; var selectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]); if (selectorLambda.Body == selectorLambda.Parameters[0]) { return(pipeline); // ignore identity projection: Select(x => x) } var selectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true); var(projectStage, projectionSerializer) = ProjectionHelper.CreateProjectStage(selectorTranslation); pipeline = pipeline.AddStages(projectionSerializer, projectStage); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__groupByMethods)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var sourceSerializer = pipeline.OutputSerializer; var keySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]); var keySelectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, keySelectorLambda, sourceSerializer, asRoot: true); var keySerializer = keySelectorTranslation.Serializer; var(elementAst, elementSerializer) = TranslateElement(context, method, arguments, sourceSerializer); var groupingSerializer = IGroupingSerializer.Create(keySerializer, elementSerializer); pipeline = pipeline.AddStages( groupingSerializer, AstStage.Group( id: keySelectorTranslation.Ast, fields: AstExpression.AccumulatorField("_elements", AstAccumulatorOperator.Push, elementAst))); if (method.IsOneOf(__groupByWithResultSelectorMethods)) { pipeline = TranslateResultSelector(context, pipeline, arguments, keySerializer, elementSerializer); } return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Join)) { var outerExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, outerExpression); var outerSerializer = pipeline.OutputSerializer; var wrapOuterStage = AstStage.Project( AstProject.Set("_outer", AstExpression.Var("ROOT")), AstProject.ExcludeId()); var wrappedOuterSerializer = WrappedValueSerializer.Create("_outer", outerSerializer); var innerExpression = arguments[1]; var(innerCollectionName, innerSerializer) = innerExpression.GetCollectionInfo(containerExpression: expression); var outerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[2]); var localFieldPath = outerKeySelectorLambda.GetFieldPath(context, wrappedOuterSerializer); var innerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[3]); var foreignFieldPath = innerKeySelectorLambda.GetFieldPath(context, innerSerializer); var lookupStage = AstStage.Lookup( from: innerCollectionName, match: new AstLookupStageEqualityMatch(localFieldPath, foreignFieldPath), @as: "_inner"); var unwindStage = AstStage.Unwind("_inner"); var resultSelectorLambda = ExpressionHelper.UnquoteLambda(arguments[4]); var root = AstExpression.Var("ROOT", isCurrent: true); var outerParameter = resultSelectorLambda.Parameters[0]; var outerField = AstExpression.GetField(root, "_outer"); var outerSymbol = context.CreateSymbol(outerParameter, outerField, outerSerializer); var innerParameter = resultSelectorLambda.Parameters[1]; var innerField = AstExpression.GetField(root, "_inner"); var innerSymbol = context.CreateSymbol(innerParameter, innerField, innerSerializer); var resultSelectorContext = context.WithSymbols(outerSymbol, innerSymbol); var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body); var(projectStage, newOutputSerializer) = ProjectionHelper.CreateProjectStage(resultSelectorTranslation); pipeline = pipeline.AddStages( newOutputSerializer, wrapOuterStage, lookupStage, unwindStage, projectStage); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(MongoQueryableMethod.DensifyWithArrayPartitionByFields)) { var sourceExpression = ConvertHelper.RemoveConvertToMongoQueryable(arguments[0]); var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var sourceSerializer = pipeline.OutputSerializer; var fieldLambda = ExpressionHelper.UnquoteLambda(arguments[1]); var fieldPath = fieldLambda.GetFieldPath(context, sourceSerializer); var rangeExpression = arguments[2]; var range = rangeExpression.GetConstantValue <DensifyRange>(expression); List <string> partitionByFieldPaths; var partitionByFieldExpressions = arguments[3]; if (partitionByFieldExpressions is NewArrayExpression newArrayExpression) { partitionByFieldPaths = new List <string>(); foreach (var partitionByFieldExpression in newArrayExpression.Expressions) { var partitionByFieldLambda = ExpressionHelper.UnquoteLambda(partitionByFieldExpression); var partitionByFieldPath = partitionByFieldLambda.GetFieldPath(context, sourceSerializer); partitionByFieldPaths.Add(partitionByFieldPath); } } else if ( partitionByFieldExpressions is ConstantExpression constantExpression && constantExpression.Value == null) { partitionByFieldPaths = null; } else { throw new ExpressionNotSupportedException(partitionByFieldExpressions, expression); } var stage = AstStage.Densify(fieldPath, range, partitionByFieldPaths); pipeline = pipeline.AddStages(sourceSerializer, stage); return(pipeline); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Distinct)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var rootVar = AstExpression.Var("ROOT", isCurrent: true); pipeline = pipeline.AddStages( pipeline.OutputSerializer, AstStage.Group(rootVar, Enumerable.Empty <AstAccumulatorField>()), AstStage.ReplaceRoot(AstExpression.GetField(rootVar, "_id"))); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Where)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var predicateLambda = ExpressionHelper.UnquoteLambda(arguments[1]); var predicateFilter = ExpressionToFilterTranslator.TranslateLambda(context, predicateLambda, parameterSerializer: pipeline.OutputSerializer); pipeline = pipeline.AddStages( pipeline.OutputSerializer, AstStage.Match(predicateFilter)); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(QueryableMethod.Take)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var countExpression = arguments[1]; var count = countExpression.GetConstantValue <int>(containingExpression: expression); pipeline = pipeline.AddStages( pipeline.OutputSerializer, AstStage.Limit(count)); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(MongoQueryableMethod.Sample)) { var sourceExpression = ConvertHelper.RemoveConvertToMongoQueryable(arguments[0]); var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); var sizeExpression = arguments[1]; var size = sizeExpression.GetConstantValue <long>(containingExpression: expression); pipeline = pipeline.AddStages( pipeline.OutputSerializer, AstStage.Sample(size)); return(pipeline); } throw new ExpressionNotSupportedException(expression); }
// 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); }
// public static methods public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__selectManyMethods)) { var sourceExpression = arguments[0]; var pipeline = ExpressionToPipelineTranslator.Translate(context, sourceExpression); if (method.Is(QueryableMethod.SelectMany)) { return(TranslateSelectMany(context, pipeline, arguments)); } if (method.Is(QueryableMethod.SelectManyWithCollectionSelectorAndResultSelector)) { return(TranslateSelectManyWithCollectionSelectorAndResultSelector(context, pipeline, arguments)); } } throw new ExpressionNotSupportedException(expression); }