更新 mongo 个文档作为一个整体或特定字段

Update mongo document as a whole or specific fields

场景

我在 mongodb 中有一个对话文档,我必须将消息添加到消息数组并更新上次发送日期,请参见下面的架构。

{ 
"_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"
    }
 ]
}

我的问题

简单地读出整个文档(使用 BsonId)并通过 c# 整体更新文档是否更有效,即将我的消息推送到数组并设置最后发送日期,然后使用驱动程序更新整个文档或使用 $set 和 $push 运算符对数据库进行两次调用以实现我想要做的事情。

我认为你不需要进行两次调用,因为MongoDB更新命令可以接受多个更新指令。 示例:

db.collection.update({_id: docId}, {$push: {values: dboVital}, $set: {endTime: time}});

因此,您可以将消息添加到您的数组中,并通过一次调用更新 lastSentDay。

正如 Eduardo Hitek 所说,您可以在单个查询中设置多个属性。 所以你可以更新实体而不必像这样首先从数据库中检索它:

    //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);

像这样更新实体的额外好处是它是自动完成的。

就像其他答案所说的那样,您可以在 $push 或 $addToSet 的帮助下在单个 mongodb 命令中完成。以下是使用我的库 MongoDB.Entities

以方便且强类型的方式完成此操作的方法
using MongoDB.Entities;
using System;

namespace Whosebug
{
    public class Program
    {
        public class Conversation : Entity
        {
            public DateTime LastSent { get; set; }
            public Message[] Messages { get; set; }
        }

        public class Message
        {
            public string Content { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test");

            var convo = new Conversation
            {
                LastSent = DateTime.Now.AddMinutes(-10),
                Messages = new[] { new Message { Content = "This is the first message..." } }
            };
            convo.Save();

            var msg = new Message { Content = "This is a new message..." };

            DB.Update<Conversation>()
              .Match(c => c.ID == convo.ID)
              .Modify(c => c.LastSent, DateTime.Now)
              .Modify(b => b.Push(c => c.Messages, msg))
              .Execute();
        }
    }
}

以下更新命令被发送到数据库:

db.Conversation.update(
    {
        "_id": ObjectId("5d0ce23647e2d210903b3930")
    },
    {
        "$set": {
            "LastSent": ISODate("2019-06-21T13:57:10.998Z")
        },
        "$push": {
            "Messages": {
                "Content": "This is a new message..."
            }
        }
    },
    {
        "multi": true,
        "upsert": false
    }
)