Search code examples
c#mongodbmongodb-.net-driver

Update mongo document as a whole or specific fields


Scenario

I have a conversation document in mongodb , I have to add messages to a messages array and update the last sent date , see schema below.

{ 
"_id" : NumberInt(5), 
"CurrentOwnerId" : NumberInt(9), 
"LastSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
"Messages" : [
    {
        "_id" : BinData(3, "nuC1iYTKtkGzSuv7pVHsKg=="), 
        "MessageContent" : "Hi There", 
        "Status" : "Pending", 
        "DateSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
        "Method" : "Slack"
    }
 ]
}

My question

Would it be more efficient to simply read out the whole document (using the BsonId) and update the document via c# as a whole ie pushing my message to the array and setting the last sent day and then updating the document as a whole using the driver OR do two calls to the database using $set and $push operators to achieve what I want to do.


Solution

  • As Eduardo Hitek said, you can set multiple properties in a single query. So you can update the entity without actually having to retrieve it from the database first like this:

        //Build an Id Filter
        var idFilter = Builders<Chat>.Filter.Eq(x => x.Id, "1");
    
    
        var message = new Message() { MessageContent = "Hey!", Method = "Slack" };
    
        //Build an update definition to add the message
        var addMessage = Builders<Chat>.Update.AddToSet(x => x.Messages, message);
        //Build an update definition to set the LastSent property
        var setLastSent = Builders<Chat>.Update.Set(x => x.LastSent, DateTime.Now);
        //Combine both update definitions
        var combinedUpdate = Builders<Chat>.Update.Combine(addMessage, setLastSent);
    
        //Execute the query.
        db.GetCollection<Chat>("ChatCollection").UpdateOne(idFilter, combinedUpdate);
    

    The added benefit from updating an entity like this is that it's done atomically.