public void Aggregate_Group_with_expressions_should_work(
            [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
        {
            var collection = GetCollection <BsonDocument>(linqProvider);

            var aggregate = collection.Aggregate()
                            .Group(x => 1, x => new { Count = x.Count() });

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = linqProvider switch
            {
                LinqProvider.V2 =>
                new[]
                {
                    "{ $group : { _id : 1, Count : { $sum : 1 } } }"
                },
                LinqProvider.V3 =>
                new[]
                {
                    "{ $group : { _id : 1, __agg0 : { $sum : 1 } } }",
                    "{ $project : { Count : '$__agg0', _id : 0 } }"
                },
                _ => throw new ArgumentException()
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void PipelineStageDefinitionBuilder_GroupForLinq3_with_expressions_should_throw_with_LINQ2()
        {
            var(groupStageDefinition, projectStageDefinition) = PipelineStageDefinitionBuilder.GroupForLinq3((BsonDocument x) => 1, x => new { Count = x.Count() });

            var exception = Record.Exception(() => Linq3TestHelpers.Render(groupStageDefinition, BsonDocumentSerializer.Instance, LinqProvider.V2));

            exception.Should().BeOfType <InvalidOperationException>();
        }
        public void PipelineDefinitionBuilder_GroupForLinq3_with_expressions_should_throw_with_LINQ2()
        {
            var emptyPipeline = (PipelineDefinition <BsonDocument, BsonDocument>) new EmptyPipelineDefinition <BsonDocument>();

            var pipeline = emptyPipeline.GroupForLinq3(x => 1, x => new { Count = x.Count() });

            var exception = Record.Exception(() => Linq3TestHelpers.Render(pipeline, BsonDocumentSerializer.Instance, LinqProvider.V2));

            exception.Should().BeOfType <InvalidOperationException>();
        }
        public void Use_documents_window_to_obtain_cumulative_and_maximum_quantity_for_each_year_example_should_work()
        {
            RequireServer.Check().Supports(Feature.SetWindowFields);
            var collection = Setup();

            var aggregate = collection
                            .Aggregate()
                            .SetWindowFields(
                partitionBy: x => x.OrderDate.Year,
                sortBy: Builders <CakeSales> .Sort.Ascending(x => x.OrderDate),
                output: p => new
            {
                CumulativeQuantityForYear = p.Sum(x => x.Quantity, DocumentsWindow.Create(DocumentsWindow.Unbounded, DocumentsWindow.Current)),
                MaximumQuantityForYear    = p.Max(x => x.Quantity, DocumentsWindow.Create(DocumentsWindow.Unbounded, DocumentsWindow.Unbounded)),
            });

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                @"
                {
                    $setWindowFields : {
                        partitionBy : { $year : '$OrderDate' } ,
                        sortBy : { OrderDate : 1 },
                        output : {
                            CumulativeQuantityForYear : {
                                $sum : '$Quantity',
                                window : {
                                    documents : ['unbounded', 'current']
                                }
                            },
                            MaximumQuantityForYear : {
                                $max : '$Quantity',
                                window : {
                                    documents : ['unbounded', 'unbounded']
                                }
                            }
                        }
                    }
                }
                "
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var results = aggregate.ToList();

            results.Count.Should().Be(6);
            results[0].Should().BeEquivalentTo("{ _id : 5, Type : 'strawberry', OrderDate : ISODate('2019-01-08T06:12:03Z'), State : 'WA', Price : 43.00, Quantity : 134, CumulativeQuantityForYear : 134, MaximumQuantityForYear : 162 }");
            results[1].Should().BeEquivalentTo("{ _id : 4, Type : 'strawberry', OrderDate : ISODate('2019-05-18T16:09:01Z'), State : 'CA', Price : 41.00, Quantity : 162, CumulativeQuantityForYear : 296, MaximumQuantityForYear : 162 }");
            results[2].Should().BeEquivalentTo("{ _id : 3, Type : 'vanilla', OrderDate : ISODate('2020-02-08T13:13:23Z'), State : 'WA', Price : 13.00, Quantity : 104, CumulativeQuantityForYear : 104, MaximumQuantityForYear : 120 }");
            results[3].Should().BeEquivalentTo("{ _id : 0, Type : 'chocolate', OrderDate : ISODate('2020-05-18T14:10:30Z'), State : 'CA', Price : 13.00, Quantity : 120, CumulativeQuantityForYear : 224, MaximumQuantityForYear : 120 }");
            results[4].Should().BeEquivalentTo("{ _id : 2, Type : 'vanilla', OrderDate : ISODate('2021-01-11T06:31:15Z'), State : 'CA', Price : 12.00, Quantity : 145, CumulativeQuantityForYear : 145, MaximumQuantityForYear : 145 }");
            results[5].Should().BeEquivalentTo("{ _id : 1, Type : 'chocolate', OrderDate : ISODate('2021-03-20T11:30:05Z'), State : 'WA', Price : 14.00, Quantity : 140, CumulativeQuantityForYear : 285, MaximumQuantityForYear : 145 }");
        }
        public void PipelineStageDefinitionBuilder_Group_with_expressions_should_work_with_LINQ2()
        {
            var stageDefinition = PipelineStageDefinitionBuilder.Group((BsonDocument x) => 1, x => new { Count = x.Count() });

            var stage          = Linq3TestHelpers.Render(stageDefinition, BsonDocumentSerializer.Instance, LinqProvider.V2);
            var expectedStages = new[]
            {
                "{ $group : { _id : 1, Count : { $sum : 1 } } }"
            };

            Linq3TestHelpers.AssertStages(new[] { stage }, expectedStages);
        }
        public void PipelineStageDefinitionBuilder_Group_with_projection_to_TOutput_should_work(
            [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
        {
            var stageDefinition = PipelineStageDefinitionBuilder.Group <BsonDocument, BsonDocument>("{ _id : 1, Count : { $sum : 1 } }");

            var stage          = Linq3TestHelpers.Render(stageDefinition, BsonDocumentSerializer.Instance, linqProvider);
            var expectedStages = new[]
            {
                "{ $group : { _id : 1, Count : { $sum : 1 } } }"
            };

            Linq3TestHelpers.AssertStages(new[] { stage }, expectedStages);
        }
        public void PipelineDefinitionBuilder_Group_with_expressions_should_work_with_LINQ2()
        {
            var emptyPipeline = (PipelineDefinition <BsonDocument, BsonDocument>) new EmptyPipelineDefinition <BsonDocument>();

            var pipeline = emptyPipeline.Group(x => 1, x => new { Count = x.Count() });

            var stages         = Linq3TestHelpers.Render(pipeline, BsonDocumentSerializer.Instance, LinqProvider.V2);
            var expectedStages = new[]
            {
                "{ $group : { _id : 1, Count : { $sum : 1 } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Where_comparing_field_name_and_index_and_nested_field_name_to_constant_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Where(x => x["field1"][2]["field3"] == 0);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { 'field1.2.field3' : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_comparing_field_names_and_two_indexes_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { AreEqual = x["field1"][2][3] == x["field4"][5][6] });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { AreEqual : { $eq : [{ $arrayElemAt : [{ $arrayElemAt : ['$field1' , 2] } , 3] }, { $arrayElemAt : [{ $arrayElemAt : ['$field4' , 5] } , 6] }] }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_comparing_two_nested_field_names_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { AreEqual = x["field1"]["field2"] == x["field3"]["field4"] });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { AreEqual : { $eq : ['$field1.field2', '$field3.field4'] }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_comparing_field_name_and__two_indexes_to_constant_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { IsZero = x["field1"][2][3] == 0 });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { IsZero : { $eq : [{ $arrayElemAt : [{ $arrayElemAt : ['$field1', 2] }, 3] }, 0] }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_comparing_nested_field_name_to_constant_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { IsZero = x["field1"]["field2"] == 0 });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { IsZero : { $eq : ['$field1.field2', 0] }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_with_field_name_and_two_indexes_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { Field = x["field1"][2][3] });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { Field : { $arrayElemAt : [{ $arrayElemAt : ['$field1', 2] } , 3] }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Select_with_nested_field_name_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { Field = x["field1"]["field2"] });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { Field : '$field1.field2', _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Where_comparing_field_names_and_two_indexes_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Where(x => x["field1"][2][3] == x["field4"][5][6]);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { $expr : { $eq : [{ $arrayElemAt : [{ $arrayElemAt : ['$field1', 2] }, 3] }, { $arrayElemAt : [{ $arrayElemAt : ['$field4', 5] }, 6] }] } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Where_comparing_two_nested_field_names_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Where(x => x["field1"]["field2"] == x["field3"]["field4"]);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { $expr : { $eq : ['$field1.field2', '$field3.field4'] } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Ternary_operator_should_work_in_Select()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Select(x => new { result = (x.A == 0 ? 42 : x.A) });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { result : { $cond : { if : { $eq : ['$A', 0] }, then : 42, else : '$A' } }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Ternary_operator_should_work_in_Where()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Where(x => (x.A == 0 ? 42 : x.A) != 144);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { $expr : { $ne : [{ $cond : { if : { $eq : ['$A', 0 ] }, then : 42, else : '$A' } }, 144] } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Where_with_lambda_should_work()
        {
            var collection = GetCollection();

            var queryable = collection.AsQueryable()
                            .Where(x => x.X > 0);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : {  X : { $gt : 0 } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void IsNullOrEmpty_in_queryable_where_should_work()
        {
            var collection = GetCollection();
            var subject    = collection.AsQueryable();

            var queryable = subject.Where(x => string.IsNullOrEmpty(x.S));

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { S : { $in : [null, ''] } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void IsNullOrEmpty_with_null_coalescing_operator_in_aggregate_match_should_work()
        {
            var collection = GetCollection();
            var subject    = collection.Aggregate();

            var aggregate = subject.Match(x => string.IsNullOrEmpty(x.S ?? ""));

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                "{ $match : { $expr : { $in : [{ $ifNull : ['$S', ''] }, [null, '']] } } }" // requires use of $expr
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Null_coalescing_operator_in_queryable_select_should_work()
        {
            var collection = GetCollection();
            var subject    = collection.AsQueryable();

            var queryable = subject.Select(x => x.S ?? "");

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { _v : { $ifNull : ['$S', ''] }, _id : 0  } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void PipelineDefinitionBuilder_Group_with_projection_to_implied_BsonDocument_should_work(
            [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
        {
            var emptyPipeline = (PipelineDefinition <BsonDocument, BsonDocument>) new EmptyPipelineDefinition <BsonDocument>();

            var pipeline = emptyPipeline.Group("{ _id : 1, Count : { $sum : 1 } }");

            var stages         = Linq3TestHelpers.Render(pipeline, BsonDocumentSerializer.Instance, linqProvider);
            var expectedStages = new[]
            {
                "{ $group : { _id : 1, Count : { $sum : 1 } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void IsNullOrEmpty_in_aggregate_match_should_work()
        {
            var collection = GetCollection();
            var subject    = collection.Aggregate();

            var aggregate = subject.Match(x => string.IsNullOrEmpty(x.S));

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                "{ $match : { S : { $in : [null, ''] } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void PipelineStageDefinitionBuilderGroupForLinq3_with_expressions_should_work_with_LINQ3()
        {
            var(groupStageDefinition, projectStageDefinition) = PipelineStageDefinitionBuilder.GroupForLinq3((BsonDocument x) => 1, x => new { Count = x.Count() });

            var groupStage         = Linq3TestHelpers.Render(groupStageDefinition, BsonDocumentSerializer.Instance, LinqProvider.V3);
            var groupingSerializer = new IGroupingSerializer <int, BsonDocument>(new Int32Serializer(), BsonDocumentSerializer.Instance);
            var projectStage       = Linq3TestHelpers.Render(projectStageDefinition, groupingSerializer, LinqProvider.V3);
            var expectedStages     = new[]
            {
                "{ $group : { _id : 1, __agg0 : { $sum : 1 } } }",
                "{ $project : { Count : '$__agg0', _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(new[] { groupStage, projectStage }, expectedStages);
        }
        public void GroupBy_with_key_selector_and_result_selector_should_translate_as_expected()
        {
            var collection = CreateCollection();
            var subject    = collection.AsQueryable();

            var queryable = subject.GroupBy(c => c.A, (k, g) => new { Result = g.First() });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $group : { _id : '$A', __agg0 : { $first : '$$ROOT' } } }",
                "{ $project : { Result : '$__agg0', _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
예제 #27
0
        public void Expression_using_ToUpperInvariant_should_work()
        {
            var collection = GetCollection();

            var queryable =
                from product in collection.AsQueryable()
                select new { Result = product.FriendlyName.ToUpperInvariant() };

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { Result : { $toUpper : '$FriendlyName' }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Aggregate_Group_with_projection_to_TNewResult_should_work(
            [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider)
        {
            var collection = GetCollection <BsonDocument>(linqProvider);

            var aggregate = collection.Aggregate()
                            .Group <Result>("{ _id : 1, Count : { $sum : 1 } }");

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                "{ $group : { _id : 1, Count : { $sum : 1 } } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void GroupBy_followed_by_select_should_translate_as_expected()
        {
            var collection = CreateCollection();
            var subject    = collection.AsQueryable();

            var queryable = subject.GroupBy(c => c.A).Select(g => new { Result = g.Select(x => x) });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $group : { _id : '$A', __agg0 : { $push : '$$ROOT' } } }",
                "{ $project : { Result : '$__agg0', _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Use_a_time_range_window_with_a_negative_upper_bound_example_should_work()
        {
            RequireServer.Check().Supports(Feature.SetWindowFields);
            var collection = Setup();

            var aggregate = collection
                            .Aggregate()
                            .SetWindowFields(
                partitionBy: x => x.State,
                sortBy: Builders <CakeSales> .Sort.Ascending(x => x.OrderDate),
                output: p => new { RecentOrders = p.Push(x => x.OrderDate, RangeWindow.Create(RangeWindow.Unbounded, RangeWindow.Months(-10))) });

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                @"
                {
                    $setWindowFields : {
                        partitionBy : '$State',
                        sortBy : { OrderDate : 1 },
                        output : {
                            RecentOrders : {
                                $push : '$OrderDate',
                                window : {
                                    range : ['unbounded', -10],
                                    unit : 'month'
                                }
                            }
                        }
                    }
                }
                "
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var results = aggregate.ToList();

            results.Count.Should().Be(6);
            results[0].Should().Be("{ _id : 4, Type : 'strawberry', OrderDate : ISODate('2019-05-18T16:09:01Z'), State : 'CA', Price : 41.00, Quantity : 162, RecentOrders : [ ] }");
            results[1].Should().Be("{ _id : 0, Type : 'chocolate', OrderDate : ISODate('2020-05-18T14:10:30Z'), State : 'CA', Price : 13.00, Quantity : 120, RecentOrders : [ISODate('2019-05-18T16:09:01Z')] }");
            results[2].Should().Be("{ _id : 2, Type : 'vanilla', OrderDate : ISODate('2021-01-11T06:31:15Z'), State : 'CA', Price : 12.00, Quantity : 145, RecentOrders : [ISODate('2019-05-18T16:09:01Z')] }");
            results[3].Should().Be("{ _id : 5, Type : 'strawberry', OrderDate : ISODate('2019-01-08T06:12:03Z'), State : 'WA', Price : 43.00, Quantity : 134, RecentOrders : [ ] }");
            results[4].Should().Be("{ _id : 3, Type : 'vanilla', OrderDate : ISODate('2020-02-08T13:13:23Z'), State : 'WA', Price : 13.00, Quantity : 104, RecentOrders : [ISODate('2019-01-08T06:12:03Z')] }");
            results[5].Should().Be("{ _id : 1, Type : 'chocolate', OrderDate : ISODate('2021-03-20T11:30:05Z'), State : 'WA', Price : 14.00, Quantity : 140, RecentOrders : [ISODate('2019-01-08T06:12:03Z'), ISODate('2020-02-08T13:13:23Z')] }");
        }