示例#1
0
        private async Task RolesSamples()
        {
            var tripsDatabase                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection          = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersQueryableCollection = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection).AsQueryable();
            var travelersBsonCollection      = tripsDatabase.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

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

            #endregion

            #region Linq

            #endregion


            #region Shell commands

#if false
#endif

            #endregion
        }
示例#2
0
        private async Task CollectionSamples()
        {
            var database = Client.GetDatabase(Constants.SamplesDatabase);

            #region Typed classes commands

            // Will create the users collection on the fly if it doesn't exists
            var personsCollection     = database.GetCollection <User>(Constants.UsersCollection);
            var bsonPersonsCollection = database.GetCollection <BsonDocument>(Constants.UsersCollection);

            User typedUser = RandomData.GenerateUsers(1).First();
            await personsCollection.InsertOneAsync(typedUser);

            // Create another collection
            var loginsCollectionName = "logins";
            await database.CreateCollectionAsync(loginsCollectionName);

            // list collections
            var collections = (await database.ListCollectionsAsync()).ToList();
            Utils.Log(collections, "List Collections");

            // remove collection
            await database.DropCollectionAsync(loginsCollectionName);

            #region Capped collection

            // create a capped collection
            // 'size' field is required when 'capped' is true
            await database
            .CreateCollectionAsync(Constants.TravelersCollection,
                                   new CreateCollectionOptions()
            {
                Capped = true, MaxDocuments = 3, MaxSize = 10000
            });

            var travelers          = RandomData.GenerateTravelers(3);
            travelers.First().Name = "Christos";

            var travelersCollection = database
                                      .GetCollection <Traveler>(Constants.TravelersCollection);

            await travelersCollection.InsertManyAsync(travelers);

            // Max documents reached - Now let's insert another one
            await travelersCollection.InsertManyAsync(RandomData.GenerateTravelers(1));

            // Read all the docs
            var dbTravelers = await travelersCollection.Find(Builders <Traveler> .Filter.Empty).ToListAsync();

            // First user 'Christos' has been removed from the collection so that the new one can fit in

            #endregion


            #endregion
        }
示例#3
0
        private async Task BucketSamples()
        {
            var database                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection     = database.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersBsonCollection = database.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

            await travelersCollection.InsertManyAsync(RandomData.GenerateTravelers(40, 5));

            #endregion

            #region Typed

            var aggregate = travelersCollection.Aggregate();

            var bucket = aggregate.Bucket(
                t => t.Age,
                new[] { 20, 32, 45, 60, 80 },
                g => new
            {
                _id            = default(int),
                averageAge     = g.Average(e => e.Age),
                totalTravelers = g.Count()
            });

            var bucketResults = await bucket.ToListAsync();

            var autoBucket = aggregate.BucketAuto(t => t.Age, 4);

            var autoBucketResults = await autoBucket.ToListAsync();

            #endregion

            #region BsonDocument commands

            var bsonAggregate = travelersBsonCollection.Aggregate();
            var bsonGroupBy   = (AggregateExpressionDefinition <BsonDocument, BsonValue>) "$age";
            var bsonBuckets   = 4;
            var bsonOutput    = (ProjectionDefinition <BsonDocument, BsonDocument>)
                                "{ averageAge : { $avg : \"$age\" }, totalTravelers : { $sum : 1 } }";
            var bsonBucketAuto = bsonAggregate.BucketAuto(bsonGroupBy, bsonBuckets, bsonOutput);

            var bsonBucketResults = await bsonBucketAuto.ToListAsync();

            #endregion

            #region Shell commands

            #if false
            db.travelers.aggregate([
示例#4
0
        private async Task FilterSamples()
        {
            var tripsDatabase                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection          = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersQueryableCollection = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection).AsQueryable();
            var travelersBsonCollection      = tripsDatabase.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

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

            #endregion

            #region Linq

            // $filter visited once

            var filterQuery = from t in travelersQueryableCollection
                              select new
            {
                t.Name,
                visitedCountries = t.VisitedCountries.Where(c => c.TimesVisited == 1)
            };

            var filterQueryResults = await filterQuery.ToListAsync();

            foreach (var result in filterQueryResults)
            {
                Utils.Log($"Age: {result.Name} - country visited once: {string.Join(',', result.visitedCountries.Select(c => c.Name))}");
            }

            var filterProjection = Builders <Traveler> .Projection.Expression(u =>
                                                                              new
            {
                name             = u.Name,
                visitedCountries = u.VisitedCountries.Where(c => c.TimesVisited == 1)
            });

            var filterProjectionResults = await travelersCollection.Find(Builders <Traveler> .Filter.Empty)
                                          .Project(filterProjection)
                                          .ToListAsync();


            #endregion

            #region BsonDocument commands

            var bsonFilterPipeline = new[]
            {
                new BsonDocument()
                {
                    {
                        "$project", new BsonDocument()
                        {
                            { "name", "$name" },
                            { "visitedCountries", new BsonDocument()
                              {
                                  { "$filter", new BsonDocument()
                                    {
                                        { "input", "$visitedCountries" },
                                        { "as", "c" },
                                        { "cond", new BsonDocument()
                                            {
                                                { "$eq", new BsonArray()
                                                        {
                                                            "$$c.timesVisited", 1
                                                        } }
                                            } }
                                    } }
                              } },
                            { "_id", 0 }
                        }
                    }
                }
            };

            var bsonFilterPipelineResults = await travelersBsonCollection.Aggregate <BsonDocument>(bsonFilterPipeline).ToListAsync();

            foreach (var result in bsonFilterPipelineResults)
            {
            }

            #endregion


            #region Shell commands

        #if false
            db.travelers.aggregate([
示例#5
0
        private async Task UnWindSamples()
        {
            var tripsDatabase                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection          = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersQueryableCollection = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection).AsQueryable();
            var travelersBsonCollection      = tripsDatabase.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

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

            #endregion

            #region Linq

            // $addToSet with Distinct
            var linqQuery = travelersQueryableCollection
                            .SelectMany(t => t.Activities, (t, a) => new
            {
                age      = t.Age,
                activity = a
            })
                            .GroupBy(q => q.age)
                            .Select(g => new { age = g.Key, activities = g.Select(a => a.activity).Distinct() })
                            .OrderBy(r => r.age);

            var linqQueryResults = await linqQuery.ToListAsync();

            foreach (var result in linqQueryResults)
            {
                Utils.Log($"Age: {result.age} - activities: {string.Join(',', result.activities)}");
            }
            #endregion

            #region BsonDocument commands

            var bsonPipeline = new[]
            {
                new BsonDocument()
                {
                    { "$unwind", "$activities" }
                },
                new BsonDocument()
                {
                    { "$group", new BsonDocument()
                      {
                          { "_id", "$age" },
                          {
                              "activities", new BsonDocument()
                              {
                                  { "$addToSet", "$activities" }
                              }
                          }
                      } }
                },
                new BsonDocument()
                {
                    { "$sort", new BsonDocument()
                      {
                          { "_id", 1 }
                      } }
                },
            };

            var results = await travelersBsonCollection.Aggregate <BsonDocument>(bsonPipeline).ToListAsync();

            foreach (var result in results)
            {
                //Utils.Log($"Age: {result.GetValue("_id").AsInt32} - activities: {result.GetValue("activities").AsBsonArray.ToString()}");
            }

            #endregion

            #region Shell commands

#if false
            db.travelers.aggregate()
            .unwind("$activities")
            .group({
                _id: { age: "$age" }, activities: { $addToSet: "$activities" }
示例#6
0
        private async Task ProjectionSamples()
        {
            var personsDatabase          = Client.GetDatabase(Constants.SamplesDatabase);
            var collection               = personsDatabase.GetCollection <User>(Constants.UsersCollection);
            var usersQueryableCollection = personsDatabase.GetCollection <User>(Constants.UsersCollection).AsQueryable();
            var bsonCollection           = personsDatabase.GetCollection <BsonDocument>(Constants.UsersCollection);

            var tripsDatabase       = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection);

            #region Prepare data

            await collection.InsertManyAsync(RandomData.GenerateUsers(500));

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

            #endregion

            #region Typed classes commands

            // exclude id, return only gender and date of birth
            var simpleProjection = Builders <User> .Projection
                                   .Exclude(u => u.Id)
                                   .Include(u => u.Gender)
                                   .Include(u => u.DateOfBirth);

            var simpleProjectionResults = await collection
                                          .Find(Builders <User> .Filter.Empty)
                                          .Project(simpleProjection)
                                          .ToListAsync();

            // return full name (first & last name), gender ('Male' or 'Female'), age
            //var lastNameProjection = Builders<User>.Projection.Expression(u => u.FirstName + " " + u.LastName);
            var customProjection = Builders <User> .Projection.Expression(u =>
                                                                          new
            {
                fullName      = $"{u.FirstName} {u.LastName}",
                fullNameUpper = ToUpperCase($"{u.FirstName} {u.LastName}"),
                gender        = u.Gender.ToString(),
                age           = DateTime.Today.Year - u.DateOfBirth.Year
            });

            var results = await collection.Find(Builders <User> .Filter.Empty)
                          .Project(customProjection)
                          .ToListAsync();

            foreach (var result in results)
            {
                Utils.Log(result.ToBsonDocument());
            }

            #endregion

            #region BsonDocument commands

            var bsonSimpleProjection = Builders <BsonDocument> .Projection
                                       .Exclude("_id")
                                       .Include("gender")
                                       .Include("dateOfBirth");

            var bsonSimpleProjectionResults = await bsonCollection
                                              .Find(Builders <BsonDocument> .Filter.Empty)
                                              .Project(bsonSimpleProjection)
                                              .ToListAsync();

            #endregion

            #region Linq

            var linqSimpleProjection =
                from u in usersQueryableCollection
                select new
            {
                fullName      = u.FirstName + " " + u.LastName,
                fullNameUpper = ToUpperCase($"{u.FirstName} {u.LastName}"),
                gender        = u.Gender == Gender.Male ? "Male" : "Female",
                age           = DateTime.Now.Year - u.DateOfBirth.Year
            };

            Utils.Log($"Query built: {linqSimpleProjection}");
            var linqSimpleProjectionResults = await linqSimpleProjection.ToListAsync();

            #endregion

            #region Shell commands

#if false
            db.users.aggregate([
示例#7
0
        private async Task MatchStageSamples()
        {
            var personsDatabase         = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersDatabase       = Client.GetDatabase(Constants.SamplesDatabase);
            var personsCollection       = personsDatabase.GetCollection <User>(Constants.UsersCollection);
            var personsBsonCollection   = personsDatabase.GetCollection <BsonDocument>(Constants.UsersCollection);
            var travelersCollection     = travelersDatabase.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersBsonCollection = travelersDatabase.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

            await personsCollection.InsertManyAsync(RandomData.GenerateUsers(500));

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

            #endregion

            #region Typed classes commands

            var aggregate = personsCollection.Aggregate()
                            .Match(Builders <User> .Filter.Gte(u => u.Salary, 3500) &
                                   Builders <User> .Filter.Lte(u => u.Salary, 5000));

            var highSalaryUsers = await aggregate.ToListAsync();

            Utils.Log($"{highSalaryUsers.Count} users found with high salary");

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

            // match with project
            var simpleProjection = Builders <Traveler> .Projection
                                   .Include(t => t.Name)
                                   .Include(t => t.Age)
                                   .Include(t => t.VisitedCountries);

            var greeceAggregate = travelersCollection
                                  .Aggregate()
                                  .Match(visitedGreeceExactly3Times)
                                  .Project(simpleProjection);

            var greeceVisited3Times = await greeceAggregate.ToListAsync();

            #endregion

            #region BsonDocument commands

            var bsonAggregate = personsBsonCollection.Aggregate()
                                .Match(Builders <BsonDocument> .Filter.Gte("salary", 3500) &
                                       Builders <BsonDocument> .Filter.Lte("salary", 5000));

            var bsonHighSalaryUsers = await bsonAggregate.ToListAsync();

            var bsonSimpleProjection = Builders <BsonDocument> .Projection
                                       .Include("name")
                                       .Include("age")
                                       .Include("visitedCountries");

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

            var bsonGreeceAggregate = travelersBsonCollection
                                      .Aggregate()
                                      .Match(bsonVisitedGreeceExactly3Times)
                                      .Project(bsonSimpleProjection);

            var bsonGreeceVisited3Times = await bsonGreeceAggregate.ToListAsync();

            #endregion

            #region Shell commands

#if false
            db.users.aggregate([
示例#8
0
        private async Task SliceSamples()
        {
            var tripsDatabase                = Client.GetDatabase(Constants.SamplesDatabase);
            var travelersCollection          = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection);
            var travelersQueryableCollection = tripsDatabase.GetCollection <Traveler>(Constants.TravelersCollection).AsQueryable();
            var travelersBsonCollection      = tripsDatabase.GetCollection <BsonDocument>(Constants.TravelersCollection);

            #region Prepare data

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

            #endregion

            #region Linq

            // $slice

            var sliceQuery = from t in travelersQueryableCollection
                             select new { t.Name, visitedCountries = t.VisitedCountries.Take(1) };

            var sliceQueryResults = await sliceQuery.ToListAsync();

            foreach (var result in sliceQueryResults)
            {
                Utils.Log($"Age: {result.Name} - countries: {string.Join(',', result.visitedCountries.FirstOrDefault()?.Name)}");
            }

            var sliceProjection = Builders <Traveler> .Projection.Expression(u =>
                                                                             new
            {
                name             = u.Name,
                visitedCountries = u.VisitedCountries.Take(1)
            });

            var sliceProjectionResults = await travelersCollection.Find(Builders <Traveler> .Filter.Empty)
                                         .Project(sliceProjection)
                                         .ToListAsync();


            // retrieve the last two visited countries
            var sliceQueryTwoLastCountries = from t in travelersQueryableCollection
                                             select new { t.Name, visitedCountries = t.VisitedCountries.Take(-2) };

            var sliceQueryTwoLastCountriesResults = await sliceQueryTwoLastCountries.ToListAsync();

            // slice with skip

            var sliceWithSkipQuery = from t in travelersQueryableCollection
                                     select new { t.Name, visitedCountries = t.VisitedCountries.Skip(2).Take(3) };

            var sliceWithSkipQueryResults = await sliceQuery.ToListAsync();

            #endregion

            #region BsonDocument commands

            var bsonSlicePipeline = new[]
            {
                new BsonDocument()
                {
                    { "$project", new BsonDocument()
                      {
                          { "name", 1 },
                          {
                              "visitedCountries", new BsonDocument()
                              {
                                  { "$slice", new BsonArray()
                                    {
                                        "$visitedCountries", 1
                                    } }
                              }
                          }
                      } }
                }
            };

            var bsonSlicePipelineResults = await travelersBsonCollection.Aggregate <BsonDocument>(bsonSlicePipeline).ToListAsync();

            foreach (var result in bsonSlicePipelineResults)
            {
            }

            #endregion


            #region Shell commands

#if false
            db.travelers.aggregate()
            .project({ name: 1, visitedCountries: { $slice:["$visitedCountries", 1] } })
示例#9
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" })
示例#10
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
                    }
                },
            },