// public static methods
        public static ExecutableQuery <TDocument, int> Translate <TDocument>(MongoQueryProvider <TDocument> provider, TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__countMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                if (method.IsOneOf(__countWithPredicateMethods))
                {
                    var predicateLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                    var predicateFilter = ExpressionToFilterTranslator.TranslateLambda(context, predicateLambda, parameterSerializer: pipeline.OutputSerializer);

                    pipeline = pipeline.AddStages(
                        pipeline.OutputSerializer,
                        AstStage.Match(predicateFilter));
                }

                pipeline = pipeline.AddStages(
                    __wrappedInt32Serializer,
                    AstStage.Count("_v"));

                return(ExecutableQuery.Create(
                           provider.Collection,
                           provider.Options,
                           pipeline,
                           _finalizer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemplo n.º 2
0
        // 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);
        }
        public static AstFilter Translate(TranslationContext context, UnaryExpression expression)
        {
            var operandExpression = expression.Operand;

            if (operandExpression.Type == typeof(bool))
            {
                var operandTranslation = ExpressionToFilterTranslator.Translate(context, operandExpression);
                return(AstFilter.Not(operandTranslation));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemplo n.º 4
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 AstFilter Translate(TranslationContext context, BinaryExpression expression)
        {
            var leftExpression  = expression.Left;
            var rightExpression = expression.Right;

            if (leftExpression.Type == typeof(bool) && rightExpression.Type == typeof(bool))
            {
                var leftTranslation  = ExpressionToFilterTranslator.Translate(context, leftExpression);
                var rightTranslation = ExpressionToFilterTranslator.Translate(context, rightExpression);
                return(AstFilter.Or(leftTranslation, rightTranslation));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Exemplo n.º 6
0
        public void Nested_Any_should_translate_correctly()
        {
            var expression         = (Expression <Func <Document, bool> >)(document => document.Details.A.Any(x => x.Any(y => Regex.IsMatch(y.DeviceName, @".Name0."))));
            var parameter          = expression.Parameters[0];
            var serializerRegistry = BsonSerializer.SerializerRegistry;
            var documentSerializer = serializerRegistry.GetSerializer <Document>();
            var context            = TranslationContext.Create(expression, documentSerializer);
            var symbol             = context.CreateSymbol(parameter, documentSerializer, isCurrent: true);

            context = context.WithSymbol(symbol);
            var filter = ExpressionToFilterTranslator.Translate(context, expression.Body, exprOk: false);

            var rendered = filter.Render();

            rendered.Should().Be("{ 'Details.A' : { $elemMatch : { $elemMatch : { DeviceName : /.Name0./ } } } }");
        }
Exemplo n.º 7
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);
        }
        private void Assert <TDocument>(Expression <Func <TDocument, bool> > expression, int expectedCount, string expectedFilter)
        {
            expression = (Expression <Func <TDocument, bool> >)PartialEvaluator.EvaluatePartially(expression);

            var parameter  = expression.Parameters.Single();
            var serializer = BsonSerializer.LookupSerializer <TDocument>();
            var context    = TranslationContext.Create(expression, serializer);
            var symbol     = context.CreateSymbol(parameter, serializer, isCurrent: true);

            context = context.WithSymbol(symbol);
            var filterAst      = ExpressionToFilterTranslator.Translate(context, expression.Body);
            var renderedFilter = (BsonDocument)filterAst.Render();

            renderedFilter.Should().Be(expectedFilter);

            var filter = new BsonDocumentFilterDefinition <C>(renderedFilter);
            var list   = __collection.FindSync <TDocument>(filter).ToList();

            list.Count.Should().Be(expectedCount);
        }
Exemplo n.º 9
0
        public List <TDocument> Assert <TDocument>(IMongoCollection <TDocument> collection, Expression <Func <TDocument, bool> > filter, int expectedCount, BsonDocument expectedFilter)
        {
            filter = (Expression <Func <TDocument, bool> >)PartialEvaluator.EvaluatePartially(filter);

            var serializer = BsonSerializer.SerializerRegistry.GetSerializer <TDocument>();
            var parameter  = filter.Parameters.Single();
            var context    = TranslationContext.Create(filter, serializer);
            var symbol     = context.CreateSymbol(parameter, serializer, isCurrent: true);

            context = context.WithSymbol(symbol);
            var filterAst      = ExpressionToFilterTranslator.Translate(context, filter.Body);
            var filterDocument = (BsonDocument)filterAst.Render();

            filterDocument.Should().Be(expectedFilter);

            var list = collection.FindSync(filterDocument).ToList();

            list.Count.Should().Be(expectedCount);
            return(list);
        }
        // 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);
        }
        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);
                }
            }
Exemplo n.º 12
0
        // public methods
        public static ExecutableQuery <TDocument, TOutput> Translate <TDocument>(MongoQueryProvider <TDocument> provider, TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__lastMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);

                if (method.IsOneOf(__lastWithPredicateMethods))
                {
                    var predicateLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                    var predicateFilter = ExpressionToFilterTranslator.TranslateLambda(context, predicateLambda, parameterSerializer: pipeline.OutputSerializer);

                    pipeline = pipeline.AddStages(
                        pipeline.OutputSerializer,
                        AstStage.Match(predicateFilter));
                }

                pipeline = pipeline.AddStages(
                    pipeline.OutputSerializer,
                    AstStage.Group(
                        id: BsonNull.Value,
                        fields: AstExpression.AccumulatorField("_last", AstAccumulatorOperator.Last, AstExpression.Var("ROOT"))));

                var finalizer = method.Name == "LastOrDefault" ? __singleOrDefaultFinalizer : __singleFinalizer;

                return(ExecutableQuery.Create(
                           provider.Collection,
                           provider.Options,
                           pipeline,
                           finalizer));
            }

            throw new ExpressionNotSupportedException(expression);
        }