更新 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
}
)
场景
我在 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
}
)