【问题标题】:Update mongo document as a whole or specific fields整体或特定字段更新 mongo 文档
【发布时间】:2019-06-21 22:04:42
【问题描述】:

场景

我在 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 运算符对数据库进行两次调用以实现我想要做的事情。

【问题讨论】:

    标签: c# mongodb mongodb-.net-driver


    【解决方案1】:

    正如 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);
    

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

    【讨论】:

    • 没有必要构建这样的过滤器。只需添加 .UpdateOne(x => x.Id == id, combinedUpdate);
    【解决方案2】:

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

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

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

    【讨论】:

    • 谢谢你 - 我一直在寻找 C# 的方法。
    【解决方案3】:

    就像其他答案所说,您可以在 $push 或 $addToSet 的帮助下在单个 mongodb 命令中完成。这是使用我的库MongoDB.Entities以方便且强类型的方式进行操作的方法@

    using MongoDB.Entities;
    using System;
    
    namespace StackOverflow
    {
        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
        }
    )
    

    【讨论】:

    • 谢谢你,我看了看你的图书馆,我很喜欢。虽然我还不能使用它,但我想知道这种(实体框架)之类的方法是否允许工作单元模式?
    • @cl0ud 我相信...通过正确使用multi-document transactions,您可以构建自己的工作单元类。如果您需要将 mongodb 逻辑与业务逻辑隔离,您还可以通过包装库方法来构建自己的存储库、服务、管理器等。但是,如果您的项目是中小型项目,并且您不希望将来切换数据库技术,那么您不需要所有中间人,因为该库基本上是一个通用存储库,您可以直接使用它。
    猜你喜欢
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多