public void Use_a_time_range_window_with_a_positive_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 : [ISODate('2019-05-18T16:09:01Z')] }");
            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'), ISODate('2020-05-18T14:10:30Z'), ISODate('2021-01-11T06:31:15Z')] }");
            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'), ISODate('2020-05-18T14:10:30Z'), ISODate('2021-01-11T06:31:15Z')] }");
            results[3].Should().Be("{ _id : 5, Type : 'strawberry', OrderDate : ISODate('2019-01-08T06:12:03Z'), State : 'WA', Price : 43.00, Quantity : 134, RecentOrders : [ISODate('2019-01-08T06:12:03Z')] }");
            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'), ISODate('2020-02-08T13:13:23Z')] }");
            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'), ISODate('2021-03-20T11:30:05Z')] }");
        }
        public void Where_with_dynamically_created_predicate_should_work(
            [Values("x", null)] string parameterName)
        {
            var collection = GetCollection();
            var predicate  = MakePredicate(parameterName);

            var queryable = collection.AsQueryable()
                            .Where(predicate);

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

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
예제 #3
0
        public void ToLower_with_Equals_should_work_in_Select()
        {
            var client     = DriverTestConfiguration.Linq3Client;
            var database   = client.GetDatabase("test");
            var collection = database.GetCollection <C>("test");

            var queryable = collection.AsQueryable()
                            .Select(x => new { Result = x.S.ToLower().Equals("abc") });

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

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
예제 #4
0
        public void ToLower_with_Equals_should_work_in_Where()
        {
            var client     = DriverTestConfiguration.Linq3Client;
            var database   = client.GetDatabase("test");
            var collection = database.GetCollection <C>("test");

            var queryable = collection.AsQueryable()
                            .Where(x => x.S.ToLower().Equals("abc"));

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { S : /^abc$/is } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Use_documents_window_to_obtain_cumulative_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)) });

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

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var results = aggregate.ToList();

            results.Count.Should().Be(6);
            results[0].Should().Be("{ _id : 5, Type : 'strawberry', OrderDate : ISODate('2019-01-08T06:12:03Z'), State : 'WA', Price : 43.00, Quantity : 134, CumulativeQuantityForYear : 134 }");
            results[1].Should().Be("{ _id : 4, Type : 'strawberry', OrderDate : ISODate('2019-05-18T16:09:01Z'), State : 'CA', Price : 41.00, Quantity : 162, CumulativeQuantityForYear : 296 }");
            results[2].Should().Be("{ _id : 3, Type : 'vanilla', OrderDate : ISODate('2020-02-08T13:13:23Z'), State : 'WA', Price : 13.00, Quantity : 104, CumulativeQuantityForYear : 104 }");
            results[3].Should().Be("{ _id : 0, Type : 'chocolate', OrderDate : ISODate('2020-05-18T14:10:30Z'), State : 'CA', Price : 13.00, Quantity : 120, CumulativeQuantityForYear : 224 }");
            results[4].Should().Be("{ _id : 2, Type : 'vanilla', OrderDate : ISODate('2021-01-11T06:31:15Z'), State : 'CA', Price : 12.00, Quantity : 145, CumulativeQuantityForYear : 145 }");
            results[5].Should().Be("{ _id : 1, Type : 'chocolate', OrderDate : ISODate('2021-03-20T11:30:05Z'), State : 'WA', Price : 14.00, Quantity : 140, CumulativeQuantityForYear : 285 }");
        }
        public void Range_window_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.Price),
                output: p => new { QuantityFromSimilarOrders = p.Sum(x => x.Quantity, RangeWindow.Create(-10, 10)) });

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                @"
                {
                    $setWindowFields : {
                        partitionBy : '$State',
                        sortBy : { Price : 1 },
                        output : {
                            QuantityFromSimilarOrders : {
                                $sum : '$Quantity',
                                window : {
                                    range : [-10.0, 10.0]
                                }
                            }
                        }
                    }
                }
                "
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var results = aggregate.ToList();

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

            var queryable =
                from product in collection.AsQueryable()
                where product.FriendlyName.ToLower() == friendlyName.ToLower()
                select product;

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { FriendlyName : /^widget$/is } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
예제 #8
0
        public void ToUpperInvariant_with_Equals_should_work()
        {
            var collection   = GetCollection();
            var friendlyName = "Widget";

            var queryable =
                from product in collection.AsQueryable()
                where product.FriendlyName.ToUpperInvariant().Equals(friendlyName.ToUpper())
                select product;

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $match : { FriendlyName : /^WIDGET$/is } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Group_with_First_should_work()
        {
            var client     = DriverTestConfiguration.Linq3Client;
            var database   = client.GetDatabase("test");
            var collection = database.GetCollection <C>("test");

            var aggregate = collection.Aggregate()
                            .SortByDescending(x => x.CreatedDate)
                            .Group(x => x.Key, g => g.First());

            var stages         = Linq3TestHelpers.Translate(collection, aggregate);
            var expectedStages = new[]
            {
                "{ $sort : { CreatedDate : -1 } }",
                "{ $group : { _id : '$Key', __agg0 : { $first : '$$ROOT' } } }",
                "{ $project : { _v : '$__agg0', _id : 0  } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
예제 #10
0
        public void Nested_Select_should_work()
        {
            var client     = DriverTestConfiguration.Linq3Client;
            var database   = client.GetDatabase("FooBar");
            var collection = database.GetCollection <FooNest>("Foos");

            database.DropCollection("Foos");

            collection.InsertOne(
                new FooNest
            {
                Name             = "Parent",
                NestedCollection = new[] {
                    new FooNest {
                        Name = "Child"
                    }
                }
            });

            var queryable = collection.AsQueryable()
                            .Select(top => top.NestedCollection.Select(child => new { ParentName = top.Name, child.Name }));

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { _v : { $map : { input : '$NestedCollection', as : 'child', in : { ParentName : '$Name', Name : '$$child.Name' } } }, _id : 0 } }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var pipelineDefinition = new BsonDocumentStagePipelineDefinition <FooNest, BsonDocument>(stages);
            var resultAsDocument   = collection.Aggregate(pipelineDefinition).ToList().Single();

            resultAsDocument.Should().Be("{ _v : [{ ParentName : 'Parent', Name : 'Child' }] }");

            var result = queryable.ToList().Single().ToList();

            result.Should().HaveCount(1);
            result[0].ParentName.Should().Be("Parent");
            result[0].Name.Should().Be("Child");
        }
        public void DefaultIfEmpty_with_explicit_default_should_work()
        {
            var client     = DriverTestConfiguration.Linq3Client;
            var database   = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
            var collection = database.GetCollection <C>(DriverTestConfiguration.CollectionNamespace.CollectionName);
            var subject    = collection.AsQueryable();

            database.DropCollection(collection.CollectionNamespace.CollectionName);
            collection.InsertMany(new[] {
                new C {
                    Id = 1, InnerArray = new A[0]
                },
                new C {
                    Id = 2, InnerArray = new[] { new A {
                                                     S = "abc"
                                                 } }
                }
            });

            var defaultValue = new A {
                S = "default"
            };
            var queryable = subject.SelectMany(outerObject => outerObject.InnerArray.DefaultIfEmpty(defaultValue), (o, a) => new { o, a });

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { _v : { $map : { input : { $let : { vars : { source : '$InnerArray' }, in : { $cond : { if : { $eq : [{ $size : '$$source' }, 0] }, then : [{ S : 'default' }], else : '$$source' } } } }, as : 'a', in : { o : '$$ROOT', a : '$$a' } } }, _id : 0 } }",
                "{ $unwind : '$_v' }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var result = queryable.ToList();

            result.Count.Should().Be(2);
            result[0].o.Id.Should().Be(1);
            result[0].a.S.Should().Be("default");
            result[1].o.Id.Should().Be(2);
            result[1].a.S.Should().Be("abc");
        }
        public void Select_with_anonymous_type_followed_by_Where_and_Select_should_work()
        {
            var collection = CreateCollection();
            var subject    = collection.AsQueryable();

            var tags      = new[] { "tag1", "tag2" };
            var queryable = subject
                            .Select(c => new { doc = c, dif = c.X.Except(tags) })
                            .Where(c => c.dif.Count() == 0)
                            .Select(c => c.doc);

            var stages         = Linq3TestHelpers.Translate(collection, queryable);
            var expectedStages = new[]
            {
                "{ $project : { doc : '$$ROOT', dif : { $setDifference : ['$X', ['tag1', 'tag2']] }, _id : 0 } }",
                "{ $match : { dif : { $size : 0 } } }",
                "{ $project : { _v : '$doc', _id : 0 } }" // Select becomes $project, not $replaceRoot
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);
        }
        public void Nested_Select_should_work()
        {
            var client        = DriverTestConfiguration.Linq3Client;
            var database      = client.GetDatabase("foo");
            var parents       = database.GetCollection <Parent>("parents");
            var children      = database.GetCollection <Child>("children");
            var grandChildren = database.GetCollection <GrandChild>("grandChildren");

            database.DropCollection("parents");
            database.DropCollection("children");
            database.DropCollection("grandChildren");

            parents.InsertMany(new[]
            {
                new Parent {
                    Id = 1, Name = "parent1"
                },
                new Parent {
                    Id = 2, Name = "parent2"
                }
            });

            children.InsertMany(new[]
            {
                new Child {
                    Id = 1, Name = "child1", ParentId = 2
                },
                new Child {
                    Id = 2, Name = "child2", ParentId = 1
                }
            });

            grandChildren.InsertMany(new[]
            {
                new GrandChild {
                    Id = 1, Name = "grandchild1", ChildId = 2
                },
                new GrandChild {
                    Id = 2, Name = "grandchild2", ChildId = 1
                }
            });

            var aggregate = parents
                            .Aggregate()
                            .Lookup <Parent, Child, ParentProjection>(
                children,
                parent => parent.Id,
                child => child.ParentId,
                parentProjection => parentProjection.Children)
                            .Lookup <ParentProjection, GrandChild, GrandChild, IEnumerable <GrandChild>, ParentProjection>(
                grandChildren,
                let: new BsonDocument {
                { "children", "$Children" }
            },
                lookupPipeline: new BsonDocumentStagePipelineDefinition <GrandChild, GrandChild>(
                    new[] { BsonDocument.Parse(@"{ $match : { $expr : { $and : [ { $in : [ ""$ChildId"", ""$$children._id"" ] } ] } } }") }),
                childProjection => childProjection.GrandChildren)
                            .Project(parent => new ParentTree
            {
                Id         = parent.Id,
                ParentName = parent.Name,
                Children   = parent.Children
                             .Select(child => new ChildTree
                {
                    Id            = child.Id,
                    Name          = child.Name,
                    GrandChildren = parent
                                    .GrandChildren
                                    .Where(gc =>
                                           gc.ChildId ==
                                           child.Id)
                                    .Select(gc =>
                                            new GrandChildProjection()
                    {
                        Id   = gc.Id,
                        Name = gc.Name
                    })
                })
            });

            var stages         = Linq3TestHelpers.Translate(parents, aggregate);
            var expectedStages = new[]
            {
                @"{
                    '$lookup':{
                        'from':'children',
                        'localField':'_id',
                        'foreignField':'ParentId',
                        'as':'Children'
                    }
                }",
                @"{
                    '$lookup':{
                        'from':'grandChildren',
                        'let':{'children':'$Children'},
                        'pipeline':[
                        {
                            '$match':{'$expr':{'$and':[{'$in':['$ChildId','$$children._id']}]}}}
                        ],
                        'as':'GrandChildren'
                    }
                }",
                @"{
                    '$project':{
                        '_id':'$_id',
                        'ParentName':'$Name',
                        'Children':{
                            '$map':{
                                'input':'$Children',
                                'as':'child',
                                'in':{
                                    '_id':'$$child._id',
                                    'Name':'$$child.Name',
                                    'GrandChildren':{
                                        '$map':{
                                            'input':{
                                                '$filter':{
                                                    'input':'$GrandChildren',
                                                    'as':'gc',
                                                    'cond':{
                                                        '$eq':[
                                                            '$$gc.ChildId',
                                                            '$$child._id'
                                                        ]
                                                    }
                                                }
                                            },
                                            'as':'gc',
                                            'in':{
                                                '_id':'$$gc._id',
                                                'Name':'$$gc.Name'
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }"
            };

            Linq3TestHelpers.AssertStages(stages, expectedStages);

            var pipelineDefinition    = new BsonDocumentStagePipelineDefinition <Parent, BsonDocument>(expectedStages.Select(s => BsonDocument.Parse(s)));
            var resultBsonDocuments   = parents.Aggregate(pipelineDefinition).ToList();
            var expectedBsonDocuments = new[]
            {
                "{ '_id' : 1, 'ParentName' : 'parent1', 'Children' : [{ '_id' : 2, 'Name' : 'child2', 'GrandChildren' : [{ '_id' : 1, 'Name' : 'grandchild1' }] }] }",
                "{ '_id' : 2, 'ParentName' : 'parent2', 'Children' : [{ '_id' : 1, 'Name' : 'child1', 'GrandChildren' : [{ '_id' : 2, 'Name' : 'grandchild2' }] }] }"
            };

            resultBsonDocuments.Should().Equal(expectedBsonDocuments.Select(d => BsonDocument.Parse(d)));

            var result          = aggregate.ToList();
            var expectedResults = new[]
            {
                new ParentTree {
                    Id = 1, ParentName = "parent1", Children = new[] { new ChildTree {
                                                                           Id = 2, Name = "child2", GrandChildren = new[] { new GrandChildProjection {
                                                                                                                                Id = 1, Name = "grandchild1"
                                                                                                                            } }
                                                                       } }
                },
                new ParentTree {
                    Id = 2, ParentName = "parent2", Children = new[] { new ChildTree {
                                                                           Id = 1, Name = "child1", GrandChildren = new[] { new GrandChildProjection {
                                                                                                                                Id = 2, Name = "grandchild2"
                                                                                                                            } }
                                                                       } }
                }
            };
            var parentTreeComparer = new ParentTreeComparer();

            result.Should().Equal(expectedResults, (x, y) => parentTreeComparer.Equals(x, y));
        }