假设我有一个mongoDB数据库,我在其中创建一个属于用户的文档,其中文档和用户都存储在数据库中。
让我们进一步说用户对象包含对文档的引用。
创建新文档可能看起来像这样。
exports.create = function (req, res, next) {
//make a new document
var newDoc = new Document({
title: req.body.title,
content: req.body.content,
});
User.findById(req.user._id, function (err, user) {
if (err)
return res.send(400);
user.documents.push(newDocument._id);
user.save(function(err){
if (err)
return res.json(400, err);
newDoc.save(function(err) {
if (err)
return res.json(400, err); //<--- What if you have an error here??
return res.json(200, {document:'successfully created'});
});
});
});
};
如果你在最后一个if(错误)时有错误,你将向用户添加对新文档的引用,但是文档将不会被创建。
当然,这是一个非常简单的案例。大量文档相互引用会使事情变得复杂得多。在Mongo / Mongoose处理这个问题最简洁的方法是什么?
答案 0 :(得分:2)
您的用户文档关系看起来像是一对多。您当前添加新文档的操作需要写入两个集合。
MongoDB不提供任何事务(可能将来会提供),因此,如果文档保存失败,您唯一的选择是从用户文档数组中删除文档ID。但它需要另一个也可能失败的写作。
为了更加原子化并在一次写入中完成所有操作,您可以将userId字段添加到Document集合中,并从User集合中删除decuments数组。
还在Document集合中的userId上创建索引。现在您的文档引用用户并创建新文档只需要一次写入。如果此写入失败,则不会保留数据库中的任何更改和一致性。
答案 1 :(得分:0)
在思考我的问题时,我遇到了这个问题......讨论了MongoDB的两个阶段提交。 http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/
这不是我接受的答案,但我认为这是相关的。