我想更新一个涉及阅读其他集合和复杂修改的文档,因此findAndModify()
中的更新操作符无法满足我的目的。
以下是我所拥有的:
Collection.findById(id, function (err, doc) {
// read from other collection, validation
// modify fields in doc according to user input
// (with decent amount of logic)
doc.save(function (err, doc) {
if (err) {
return res.json(500, { message: err });
}
return res.json(200, doc);
});
}
我担心如果多个客户端碰巧修改同一文档,此流程可能会导致冲突 据说here:
使用MongoDB数据库对单个文档的操作始终是原子的
我对Operations
的含义感到有点困惑。
findById()
将获取锁定,直到doc
超出范围(发送响应之后),因此不会发生冲突? (我不这么认为)versionKey
(或时间戳)并重试过时的文档感谢。
修改
感谢@jibsales指针,我现在使用Mongoose的versionKey
(时间戳也可以),以避免发生冲突。
aaronheckmann — Mongoose v3 part 1 :: Versioning
请参阅此示例代码:
https://gist.github.com/anonymous/9dc837b1ef2831c97fe8
答案 0 :(得分:3)
操作是指读/写。请记住,MongoDB不是符合ACID标准的数据层,如果您需要真正的ACID合规性,那么最好选择其他技术。也就是说,您可以通过两阶段提交技术outlined in this article in the MongoDB docs实现原子性和隔离。这不是一件小事,所以要为一些繁重的工作做好准备,因为你需要与本地驱动程序而不是Mongoose一起工作。同样,我的最终建议是,如果您需要交易支持,请不要喝NoSQL koolaid。听起来就是这样。
答案 1 :(得分:1)
当MongoDB收到更新文档的请求时,它将锁定数据库,直到它完成操作。 MongoDB收到的任何其他请求将等待锁定操作完成并且数据库已解锁。此锁定/等待行为是自动的,因此不需要处理任何冲突。您可以在常见问题解答的Concurrency部分找到有关此行为的更多信息。
有关进行多文档事务的MongoDB推荐技术的链接,请参阅jibsales答案。
有几个NoSQL数据库可以进行完整的ACID交易,这将使您的生活更加轻松。 FoundationDB就是这样一个数据库。数据存储为键值,但它通过图层支持多个数据模型。
完全披露:我是FoundationDB的工程师。