mongodb / mongoose,更改两个文档时如何确保数据一致

时间:2014-03-24 20:14:45

标签: mongodb mongoose consistency

假设我有一个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处理这个问题最简洁的方法是什么?

2 个答案:

答案 0 :(得分:2)

您的用户文档关系看起来像是一对多。您当前添加新文档的操作需要写入两个集合。

MongoDB不提供任何事务(可能将来会提供),因此,如果文档保存失败,您唯一的选择是从用户文档数组中删除文档ID。但它需要另一个也可能失败的写作。

为了更加原子化并在一次写入中完成所有操作,您可以将userId字段添加到Document集合中,并从User集合中删除decuments数组。

还在Document集合中的userId上创建索引。现在您的文档引用用户并创建新文档只需要一次写入。如果此写入失败,则不会保留数据库中的任何更改和一致性。

答案 1 :(得分:0)

在思考我的问题时,我遇到了这个问题......讨论了MongoDB的两个阶段提交。 http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/

这不是我接受的答案,但我认为这是相关的。