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" })
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 } }, },