更新文档时获取文档的旧版本和新版本



对于我的应用程序在MongoDB上执行的每个操作,我都希望拥有文档的旧版本和新版本,以便我可以发出两个版本的事件:

{
type: 'UPDATE',
before: documentBeforeUpdate,
after: documentAfterUpdate
}

我现在这样做的方法是首先对查询发出findOne,然后对更新进行findOneAndUpdate,但使用文档的_id进行查询。因此,如果查询实际上在数据库上引起负载,我不会为此付出两次代价:

async function updateOne(query, updates) {
const oldDocument = await this.model
.findOne(query, null, { lean: true })
.exec();
if (!oldDocument) {
return;
}
const newDocument = await this.model
.findOneAndUpdate({ _id: oldDocument._id }, updates, {
new: true,
lean: true
})
.exec();
// document vanished before it could be updated
if (!newDocument) {
return;
}
await this.emit("UPDATE", {
before: oldDocument,
after: newDocument,
type: "UPDATE"
});
return newDocument;
}

我对updateManydelete{One,Many}createOne等都有类似的功能。

现在我的问题是,是否有比这样做更高性能的方法?

上下文

我想做的是分离代码,这些代码会出于查询性能原因对数据库中的数据进行非规范化。假设我有一个应用程序,您可以在餐厅预订餐桌,那么我希望预订位于自己的集合中,但我也希望将每个表的可用性信息缓存在表自己的文档中。因此,我可以查询表的集合以查找特定时间可用的表。

// reservation
{
_id: ObjectId,
table: ObjectId,
from: Date,
to: Date
}
// table
{
_id: ObjectId,
reservations: [
{ _id: ObjectId, from: Date, to: Date },
// ...
]
}

当具有可以侦听文档的创建、更新和删除的事件系统时,我不需要直接从更新保留文档的代码调用更新表的预留属性的代码。这就是我想要实现的架构。

findAndOneUpdate 中有一个选项,称为

返回新文档:布尔值

此选项将告诉 mongodb 返回旧文档,而不是在响应对象中返回更新的文档。

来自 mongo 文档

db.collection.findOneAndUpdate(filter, update, options)

根据筛选器和排序条件更新单个文档。

findOneAndUpdate() 方法具有以下形式:

db.collection.findOneAndUpdate(
<filter>,
<update>,
{
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
upsert: <boolean>,
returnNewDocument: <boolean>,
collation: <document>
}
)

对你的代码不满意: 您的更新对象名为"updates"并传递给findAndUpdateOne应包含字段{returnNewDocument: true}, 然后你需要从findAndUpdateOne方法读取响应,这样你就可以在不运行单独的findOne查询的情况下获取旧文档。

蒙戈手册 - 查找一个和更新 https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

最新更新