Example #1
0
        private async Task ArrayOperatorsSamples()
        {
            var database       = Client.GetDatabase(Constants.SamplesDatabase);
            var collection     = database.GetCollection <Traveler>(Constants.TravelersCollection);
            var bsonCollection = database.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

            var travelers = RandomData.GenerateTravelers(500);
            await collection.InsertManyAsync(travelers);

            // ElemMatch
            var greeceAndItalyTravelers = RandomData.GenerateTravelers(15);
            foreach (var grcItTraveler in greeceAndItalyTravelers)
            {
                var firstCountry  = RandomData.GenerateVisitedCountries(1).First();
                var secondCountry = RandomData.GenerateVisitedCountries(1).First();
                var random        = new Faker().PickRandom(0, 1);
                switch (random)
                {
                case 0:
                    firstCountry.Name  = "Greece";
                    secondCountry.Name = "Italy";
                    break;

                default:
                    firstCountry.Name  = "Italy";
                    secondCountry.Name = "Greece";
                    break;
                }

                grcItTraveler.VisitedCountries = new List <VisitedCountry> {
                    firstCountry, secondCountry
                };
            }

            await collection.InsertManyAsync(greeceAndItalyTravelers);

            #endregion

            #region Typed classes commands

            // Get all travelers that have visited Greece

            //same results
            var greeceTravelers = await collection.Find(t => t.VisitedCountries.
                                                        Any(c => c.Name == "Greece")).ToListAsync();

            var italyTravelers = await collection.Find(t => t.VisitedCountries
                                                       .Any(c => c.Name == "Italy")).ToListAsync();

            var greeceItalyTravelers = await collection.Find(t => t.VisitedCountries
                                                             .Any(c => c.Name == "Greece" || c.Name == "Italy")).ToListAsync();

            // using filter - same results
            var greeceVisitedFilter = Builders <Traveler> .Filter.AnyEq("visitedCountries.name", "Greece");

            greeceTravelers = await collection.Find(greeceVisitedFilter).ToListAsync();

            Utils.Log($"{greeceTravelers.Count} total travelers have visited Greece");

            var visitedTimesFilter = Builders <Traveler> .Filter.AnyEq("visitedCountries.timesVisited", 3);

            var combinedFilter = Builders <Traveler> .Filter.And(greeceVisitedFilter, visitedTimesFilter);

            var wrongResult = await collection.Find(combinedFilter).ToListAsync();

            #region size

            var fiveVisitedCountriesFilter = await collection.Find(t => t.VisitedCountries.Count == 5).ToListAsync();

            Utils.Log($"{fiveVisitedCountriesFilter.Count} total travelers have visited 5 countries exactly");

            var moreThan10VisitedCountries = await collection.Find(t => t.VisitedCountries.Count > 10).ToListAsync();

            Utils.Log($"{moreThan10VisitedCountries.Count} total travelers have visited more than 10 countries");

            #endregion

            #region elemMatch

            var visitedGreeceExactly3Times = Builders <Traveler> .Filter.ElemMatch(t => t.VisitedCountries,
                                                                                   country => country.Name == "Greece" && country.TimesVisited == 3);

            var visitedGreeceExactly3TimesTravelers = await collection.Find(visitedGreeceExactly3Times).ToListAsync();

            Utils.Log($"{visitedGreeceExactly3TimesTravelers.Count} total travelers have visited Greece exactly 3 times");

            #region multiple conditions

            var countryNameFilter = Builders <VisitedCountry> .Filter.In(c => c.Name, new[] { "Greece", "Italy" });

            var countryTimesVisitedFilter = Builders <VisitedCountry> .Filter.Eq(c => c.TimesVisited, 3);

            var visitedGreeceOrItalyExactly3Times = Builders <Traveler> .Filter
                                                    .ElemMatch(t => t.VisitedCountries,
                                                               Builders <VisitedCountry> .Filter.And(countryNameFilter, countryTimesVisitedFilter));


            var visitedGreeceOrItalyExactly3TimesTravelers = await collection.Find(visitedGreeceOrItalyExactly3Times).ToListAsync();

            Utils.Log($"{visitedGreeceOrItalyExactly3TimesTravelers.Count} total travelers have visited Greece or Italy exactly 3 times");
            #endregion

            #endregion

            #region All

            // Order doesn't matter - items are included on the array
            var climbingAndBackpackingFilter = Builders <Traveler> .Filter
                                               .All(t => t.Activities, new List <string> {
                "Backpacking", "Climbing"
            });

            var climbingAndBackpackingTravelers = await collection.Find(climbingAndBackpackingFilter).ToListAsync();

            Utils.Log($"{climbingAndBackpackingTravelers.Count} total travelers have 'Backpacking' & 'Climbing' activities");
            #endregion

            #endregion

            #region BsonDocument commands
            var bsonGreeceVisitedFilter = Builders <BsonDocument> .Filter.AnyEq("visitedCountries.name", "Greece");

            var bsonGreeceTravelers = await bsonCollection.Find(bsonGreeceVisitedFilter).ToListAsync();

            #region size

            var bsonFiveVisitedCountriesFilter = await bsonCollection.Find(
                new BsonDocument
            {
                { "visitedCountries", new BsonDocument {
                      { "$size", 5 }
                  } }
            }).ToListAsync();

            var bsonMoreThan10VisitedCountries = await bsonCollection
                                                 .Find(new BsonDocument
            {
                { "visitedCountries.10", new BsonDocument {
                      { "$exists", true }
                  } }
            }).ToListAsync();

            Utils.Log($"{moreThan10VisitedCountries.Count} total travelers have visited more than 10 countries");

            #endregion

            #region elemmMatch

            var bsonVisitedGreeceExactly3Times = Builders <BsonDocument> .Filter
                                                 .ElemMatch <BsonValue>("visitedCountries", new BsonDocument { { "name", "Greece" }, { "timesVisited", 3 } });

            var bsonVisitedGreeceExactly3TimesTravelers = await bsonCollection.Find(bsonVisitedGreeceExactly3Times).ToListAsync();

            #region multiple conditions

            var bsonVisitedGreeceOrItalyExactly3Times = Builders <BsonDocument> .Filter
                                                        .ElemMatch <BsonValue>("visitedCountries", new BsonDocument
            {
                { "name", new BsonDocument("$in", new BsonArray {
                        "Greece", "Italy"
                    }) },
                { "timesVisited", 3 }
            });

            var bsonVisitedGreeceOrItalyExactly3TimesTravelers = await bsonCollection.Find(bsonVisitedGreeceOrItalyExactly3Times).ToListAsync();

            #endregion

            #endregion

            #region All

            var bsonClimbingAndBackpackingFilter = Builders <BsonDocument> .Filter
                                                   .All("activities", new List <string> {
                "Backpacking", "Climbing"
            });

            var bsonClimbingAndBackpackingTravelers = await bsonCollection.Find(bsonClimbingAndBackpackingFilter).ToListAsync();

            #endregion

            #endregion

            #region Shell commands

#if false
            db.travelers.find({ "visitedCountries.name" : "Greece" })
Example #2
0
        private async Task UpdatingArraysDefinitions()
        {
            var database                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection     = database.GetCollection <Traveler>(Constants.TravelersCollection);
            var bsonTravelersCollection = database.GetCollection <BsonDocument>(Constants.TravelersCollection);
            var storesCollection        = database.GetCollection <StoreItem>(Constants.StoreCollection);
            var socialNetworkCollection = database.GetCollection <SocialAccount>(Constants.SocialNetworkCollection);
            var postsCollection         = database.GetCollection <Post>(Constants.PostsCollection);
            var bsonPostsCollection     = database.GetCollection <BsonDocument>(Constants.PostsCollection);

            #region Prepare data

            await travelersCollection.InsertManyAsync(RandomData.GenerateTravelers(2));

            #endregion

            #region Typed classes commands

            #region Adding array items

            var firstTraveler  = Builders <Traveler> .Filter.Empty;
            var visitedCountry = RandomData.GenerateVisitedCountries(1).First();
            visitedCountry.Name            = "South Korea";
            visitedCountry.TimesVisited    = 5;
            visitedCountry.LastDateVisited = DateTime.UtcNow.AddYears(5);

            var pushCountryDefinition = Builders <Traveler> .Update.Push(t => t.VisitedCountries, visitedCountry);

            var addNewVisitedCountryResult = await travelersCollection.UpdateOneAsync(firstTraveler, pushCountryDefinition);

            Utils.Log("South Korea has been added to user's visited countries");

            var newVisitedCountries     = RandomData.GenerateVisitedCountries(10);
            var pushCountriesDefinition = Builders <Traveler> .Update
                                          .PushEach(t => t.VisitedCountries, newVisitedCountries);

            var addNewVisitedCountriesResult = await travelersCollection
                                               .UpdateOneAsync(firstTraveler, pushCountriesDefinition);

            #endregion

            #region Queue

            var account = RandomData.GenerateSocialAccounts(1).First();

            await socialNetworkCollection.InsertOneAsync(account);

            var firstAccount = await socialNetworkCollection.Find(Builders <SocialAccount> .Filter.Empty)
                               .FirstOrDefaultAsync();

            Utils.Log(firstAccount.ToBsonDocument());

            var newNotifications = new List <Notification>();
            for (int i = 0; i < 4; i++)
            {
                newNotifications.Add(new Notification()
                {
                    Link = $"link-{i}",
                    Text = $"text-{i}"
                });
            }

            var pushNotificationsDefinition = Builders <SocialAccount> .Update
                                              .PushEach(a => a.LastNotifications, newNotifications, slice : -2);

            var pushNotificationsResult = await socialNetworkCollection
                                          .UpdateOneAsync(Builders <SocialAccount> .Filter.Eq(a => a.Id, firstAccount.Id), pushNotificationsDefinition);

            firstAccount = await socialNetworkCollection.Find(Builders <SocialAccount> .Filter.Empty)
                           .FirstOrDefaultAsync();

            Utils.Log(firstAccount.ToBsonDocument());
            #endregion

            #region remove array items

            // add two items
            var storeItems = new List <StoreItem>
            {
                new StoreItem()
                {
                    PcGames = new List <string>
                    {
                        "Football Manager", "DOOM Eternal",
                        "FIFA 20", "Grand Theft Auto", "NBA 2K17"
                    },
                    XboxGames = new List <string>
                    {
                        "Forza Horizon", "Call of Duty",
                        "Mortal Kombat", "Gears 5"
                    }
                },
                new StoreItem()
                {
                    PcGames = new List <string>
                    {
                        "Assassin's Creed", "Final Fantasy",
                        "The Sims", "Football Manager", "FIFA 20"
                    },
                    XboxGames = new List <string>
                    {
                        "Resident Evil", "Forza Motorsport",
                        "Battlefield", "Halo 5 Guardians", "Mortal Kombat"
                    }
                }
            };

            await storesCollection.InsertManyAsync(storeItems);

            var storeEmptyFilter = Builders <StoreItem> .Filter.Empty;
            var removePcGames    = new List <string> {
                "FIFA 20", "NBA 2K17"
            };
            var removeXboxGames = new List <string> {
                "Mortal Kombat"
            };

            var pullPcGamesDefinition = Builders <StoreItem> .Update.PullFilter(s => s.PcGames,
                                                                                game => removePcGames.Contains(game));

            var pullXboxGamesDefinition = Builders <StoreItem> .Update.PullFilter(s => s.XboxGames,
                                                                                  game => removeXboxGames.Contains(game));

            var pullCombined = Builders <StoreItem> .Update
                               .Combine(pullPcGamesDefinition, pullXboxGamesDefinition);

            var simplePullResult = await storesCollection
                                   .UpdateManyAsync(storeEmptyFilter, pullPcGamesDefinition);

            // reset collection
            await database.DropCollectionAsync(Constants.StoreCollection);

            await storesCollection.InsertManyAsync(storeItems);

            var removeUpdateResult = await storesCollection
                                     .UpdateManyAsync(storeEmptyFilter, pullCombined);

            // remove embedded document

            await travelersCollection.InsertManyAsync(RandomData.GenerateTravelers(10, 15));

            var visited8Times = Builders <Traveler> .Filter
                                .ElemMatch(t => t.VisitedCountries, country => country.TimesVisited == 8);

            var totalDocVisited8Times = await travelersCollection
                                        .Find(visited8Times).CountDocumentsAsync();

            var pullVisited8TimesDefinition = Builders <Traveler> .Update
                                              .PullFilter(t => t.VisitedCountries,
                                                          country => country.TimesVisited == 8);

            var visited8TimesResult = await travelersCollection
                                      .UpdateManyAsync(visited8Times, pullVisited8TimesDefinition);

            Utils.Log($"{totalDocVisited8Times} document found with TimesVisited = 8 and {visited8TimesResult.ModifiedCount} removed");

            #endregion

            #region update matched array elements

            var visitedGreeceExactly3Times = Builders <Traveler> .Filter
                                             .ElemMatch(t => t.VisitedCountries,
                                                        country => country.Name == "Greece" && country.TimesVisited == 3);

            var updateDefinition = Builders <Traveler> .Update.Set(t => t.VisitedCountries[-1].Name, "Hellas");

            // this will update only the first matching array element! ($) refers to the first match
            var updateHellasResult = await travelersCollection.UpdateManyAsync(visitedGreeceExactly3Times, updateDefinition);

            Utils.Log($"{updateHellasResult.ModifiedCount} visited countries have been updated");

            #endregion

            #region update all matched array elements

            var visitedHellasExactly3Times = Builders <Traveler> .Filter
                                             .ElemMatch(t => t.VisitedCountries,
                                                        country => country.Name == "Greece" && country.TimesVisited == 3);

            // TODO : more with Aggregation Pipeline
            var updateGreeceDefinition = Builders <Traveler> .Update.Inc("visitedCountries.$[].timesVisited", 10);

            var updateGreeceResult = await travelersCollection.UpdateManyAsync(visitedHellasExactly3Times, updateGreeceDefinition);

            // TODO : more with Aggregation Pipeline

            var updateExactVisitedDefinition = Builders <Traveler> .Update.Inc("visitedCountries.$[el].timesVisited", 10);

            var updateExactVisitedResult = await travelersCollection.UpdateManyAsync(
                Builders <Traveler> .Filter
                .ElemMatch(t => t.VisitedCountries, country => country.Name == "Hellas")
                , updateExactVisitedDefinition,
                new UpdateOptions()
            {
                ArrayFilters = new List <ArrayFilterDefinition <VisitedCountry> >()
                {
                    "{ $and: [{ 'el.timesVisited': 13 }, { 'el.name': 'Hellas'} ] }"
                }
            });

            #endregion

            #region array filters

            var post = new Post
            {
                Author   = "chsakell",
                Content  = "hello world",
                Comments = new List <Comment>
                {
                    new Comment
                    {
                        Author = "author 1",
                        Text   = "comment 1",
                        Votes  = 1
                    },
                    new Comment
                    {
                        Author = "author 2",
                        Text   = "comment 2",
                        Votes  = 2
                    },
                    new Comment
                    {
                        Author = "author 3",
                        Text   = "comment 3",
                        Votes  = 3
                    },
                    new Comment
                    {
                        Author = "author 4",
                        Text   = "comment 4",
                        Votes  = 4
                    }
                }
            };
            await postsCollection.InsertOneAsync(post);

            var update = Builders <BsonDocument> .Update
                         .Set("comments.$[elem].hidden", true);

            var updateResult = await bsonPostsCollection.UpdateOneAsync(
                Builders <BsonDocument> .Filter.Eq("_id", post.Id), update,
                new UpdateOptions()
            {
                ArrayFilters = new List <ArrayFilterDefinition <BsonValue> >()
                {
                    new BsonDocument("elem.votes", new BsonDocument("$gte", 3))
                }
            });

            #endregion

            // TODO: pull/pop

            #endregion

            #region BsonDocument commands

            #region Adding array items

            var bsonFirstUser      = Builders <BsonDocument> .Filter.Empty;
            var bsonVisitedCountry = RandomData.GenerateVisitedCountries(1).First();
            visitedCountry.Name            = "North Korea";
            visitedCountry.TimesVisited    = 5;
            visitedCountry.LastDateVisited = DateTime.UtcNow.AddYears(5);

            var bsonPushCountryDefinition = Builders <BsonDocument> .Update
                                            .Push("visitedCountries", visitedCountry.ToBsonDocument());

            var bsonAddNewVisitedCountryResult = await bsonTravelersCollection
                                                 .UpdateOneAsync(bsonFirstUser, bsonPushCountryDefinition);

            var bsonNewVisitedCountries     = RandomData.GenerateVisitedCountries(10);
            var bsonPushCountriesDefinition = Builders <BsonDocument> .Update
                                              .PushEach("visitedCountries", bsonNewVisitedCountries);

            var bsonAddNewVisitedCountries = await bsonTravelersCollection
                                             .UpdateOneAsync(bsonFirstUser, bsonPushCountriesDefinition);

            var bsonVisited9Times = Builders <BsonDocument> .Filter
                                    .ElemMatch <BsonValue>("visitedCountries", new BsonDocument { { "timesVisited", 9 } });

            var bsonTotalDocVisited9Times = await bsonTravelersCollection
                                            .Find(bsonVisited9Times).CountDocumentsAsync();

            var bsonPullVisited9TimesDefinition = Builders <BsonDocument> .Update
                                                  .PullFilter <BsonValue>("visitedCountries",
                                                                          new BsonDocument { { "timesVisited", 9 } });

            var bsonVisited9TimesResult = await bsonTravelersCollection
                                          .UpdateManyAsync(bsonVisited9Times, bsonPullVisited9TimesDefinition);

            #endregion

            #region update matched array elements
            var bsonVisitedGreeceExactly3Times = Builders <BsonDocument> .Filter
                                                 .ElemMatch <BsonValue>("visitedCountries", new BsonDocument { { "name", "Greece" }, { "timesVisited", 3 } });

            var bsonUpdateDefinition = Builders <BsonDocument> .Update.Set("visitedCountries.$.name", "Hellas");

            var bsonUpdateHellasResult = await bsonTravelersCollection
                                         .UpdateManyAsync(bsonVisitedGreeceExactly3Times, bsonUpdateDefinition);

            #endregion

            #region update all matched array elements

            var bsonVisitedHellasExactly3Times = Builders <BsonDocument> .Filter
                                                 .ElemMatch <BsonValue>("visitedCountries", new BsonDocument { { "name", "Hellas" }, { "timesVisited", 3 } });

            // TODO : more with projection
            var bsonUpdateGreeceDefinition = Builders <BsonDocument> .Update.Inc("visitedCountries.$[].timesVisited", 10);

            var bsonUpdateGreeceResult = await bsonTravelersCollection
                                         .UpdateManyAsync(bsonVisitedHellasExactly3Times, bsonUpdateGreeceDefinition);

            #endregion

            #endregion

            #region Shell commands

#if false
            db.travelers.updateMany(
            {
                "visitedCountries" : {
                    "$elemMatch" : {
                        "timesVisited" : 8
                    }
                },
            },