dahln
dahln

Reputation: 119

MongoDB Update Array with C# Driver

Using MongoDB, How do I update a single array element within a document using the C# Driver.

Allow me to setup this up. Assume there is a collection, called "Things". Within the Things collection, there are many document. Here are two "things" documents:

{
    "_id":"2d7fcf21-34b8-4537-b07f-01659d87eda4",
    "Name":"Something",
    "Stuff":[
        {
            "Id":"1fdd098c-5e60-4dd8-a6a6-96b26cd90dc9",
            "Completed":false
        },
        {
            "Id":"b63cc911-a577-4744-bb0f-b9d9deabcf66",
            "Completed":false
        }
    ]
}


{
    "_id":"d4ba4420-238f-4e11-9ad8-721dc3eb0ad7
    ",
    "Name":"Another Thing",
    "Stuff":[
        {
            "Id":"f2d46144-15eb-4451-851a-cba80dd8949b",
            "Completed":false
        },
        {
            "Id":"f2d46144-15eb-4451-851a-cba80dd8949b",
            "Completed":false
        }
    ]
}

If I have the _id of the document, and Id of the the item in the array I want to change, how can I toggle the "Completed" property from false to true, without replacing the entire document or array?

The data I am showing here is not actual data from the application I'm working on, it is contrived for this example. Also, I am using the C# MongoDB Driver v2.7.2 and my database is running on MongoDB v4 on Atlas.

Upvotes: 5

Views: 4642

Answers (1)

mickl
mickl

Reputation: 49945

To update single item in nested array you need to use $ positional operator which requires additonal filter to represent filtering on nested array. That filter can be expressed using ElemMatch in C#. Then to refer matched subdocument you can pass -1 to the indexer of your nested array. Try:

var documentId = "2d7fcf21-34b8-4537-b07f-01659d87eda4";
var stuffId = "1fdd098c-5e60-4dd8-a6a6-96b26cd90dc9";

var filter = Builders<YourModel>.Filter.And(Builders<YourModel>.Filter.Eq(x => x._id, documentId), 
    Builders<YourModel>.Filter.ElemMatch(x => x.Stuff, f => f.Id == stuffId));

var update = Builders<YourModel>.Update.Set(model => model.Stuff[-1].Completed, true);

Col.UpdateOne(filter, update);

Upvotes: 5

Related Questions