Search code examples
c#mongodbmongodb-.net-driver

MongoDb update nested array item


I have the following database structure.

{
  "classes": [
    {
      "_id": "abcd1234",
      "classname": "11/A",
      "students": [
        {
          "_id": "student1",
          "firstname": "Don",
          "lastname": "Joe"
        },
        {
          "_id": "student2",
          "firstname": "Doo",
          "lastname": "Joe"
        },
        ...
      ]
    },
    ...
  ]
}

How can I update a student by it's id with the C# MongoDb Driver? Something like this:

public async Task UpdateStudent(string studentId, Student student)
{
    // implementation???
}

Solution

  • You can use the MongoDB positional operator ($) which in C# is just an index of -1 in the array.

    var filter = Builders<Class>.Filter.ElemMatch(x => x.Students, Builders<Student>.Filter.Eq(x => x.Id, "student2"));
    var update = Builders<Class>.Update.Set(x => x.Students[-1].Firstname, "NEW FIRST NAME")
                                        .Set(x => x.Students[-1].Lastname, "NEW LAST NAME");
    
    await collection.UpdateOneAsync(filter, update);
    
    public class Class
    {
        public string Id { get; set; }
        public string Classname { get; set; }
        public Student[] Students { get; set; }
    }
    
    public class Student
    {
        public string Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }
    

    For example if you push some documents in to our collection like the following

    var client = new MongoClient();
    var db = client.GetDatabase("test");
    var collection = db.GetCollection<Class>("classes");
    
    await collection.InsertManyAsync(new[]
    {
        new Class
        {
            Id= Guid.NewGuid().ToString(),Classname = "Class 1", Students = new Student[]
            {
                new Student{Id = "student1", Firstname = "Don", Lastname = "Joe"},
                new Student{Id = "student2", Firstname = "Doo", Lastname = "Joe"}
            }
        },
        new Class
        {
            Id= Guid.NewGuid().ToString(),Classname = "Class 1", Students = new Student[]
            {
                new Student{Id = "student3", Firstname = "Don2", Lastname = "Joe2"},
                new Student{Id = "student4", Firstname = "Doo2", Lastname = "Joe2"}
            }
        }
    });
    

    If we run the above update our data will look like the following in the shell

    > db.classes.find().pretty()
    {
            "_id" : "b0413433-199a-4df0-bef0-0c6ae13e08b9",
            "Classname" : "Class 1",
            "Students" : [
                    {
                            "_id" : "student1",
                            "Firstname" : "Don",
                            "Lastname" : "Joe"
                    },
                    {
                            "_id" : "student2",
                            "Firstname" : "NEW FIRST NAME",
                            "Lastname" : "NEW LAST NAME"
                    }
            ]
    }
    {
            "_id" : "b88c2725-3046-4717-96f2-e0553a5d3c96",
            "Classname" : "Class 1",
            "Students" : [
                    {
                            "_id" : "student3",
                            "Firstname" : "Don2",
                            "Lastname" : "Joe2"
                    },
                    {
                            "_id" : "student4",
                            "Firstname" : "Doo2",
                            "Lastname" : "Joe2"
                    }
            ]
    }
    >
    

    Check out the following post: https://kevsoft.net/2020/03/23/updating-arrays-in-mongodb-with-csharp.html