Mongoose.js交易

Zeb*_*Lab 24 transactions mongodb

我知道MongoDB不像关系数据库那样支持事务,但我仍然想知道如何实现几个操作的原子性.在网络上狩猎,我看到有人提到没有交易的交易.通过幻灯片阅读,我仍然不清楚如何使用Mongoose.js实现它.

以此代码段为例:

player.save(callback1);
story.save(callback2);
Run Code Online (Sandbox Code Playgroud)

如何实现callback1和callback2以使它们一起成功或一起失败?

Wil*_*ver 9

如果您确实必须跨多种文档类型(在单独的集合中)具有事务,则实现此目的的方法是使用单个表来存储要采取的操作.

db.actions.insert(
{ actions: [{collection: 'players', _id: 'p1', update: {$set : {name : 'bob'} } },
            {collection: 'stories', _id: 's1', update: {$set : {location: 'library'} } }], completed: false }, callback);
Run Code Online (Sandbox Code Playgroud)

这个插入是原子的,一次完成.然后,您可以在"操作"集合中执行命令并将其标记为完成,或在完成时删除它们,在完成后调用原始回调.仅当您的操作处理循环是更新数据库的唯一内容时,此方法才有效.当然你必须停止使用猫鼬,但是越快你做到这一点就越好.


oj_*_*oss 8

这个问题已经很老了,但是对于那些偶然发现这个页面的人来说,你可以使用小鹿.它是一个npm包解决了这个确切的问题.披露:我写了

假设您有两个银行账户,一个属于John Smith,另一个属于Broke Individual.您想将20美元从John Smith转移到Broke Individual.假设所有名字和姓氏对都是唯一的,这可能如下所示:

var Fawn = require("fawn");
var task = Fawn.Task()

//assuming "Accounts" is the Accounts collection 
task.update("Accounts", {firstName: "John", lastName: "Smith"}, {$inc: {balance: -20}})
  .update("Accounts", {firstName: "Broke", lastName: "Individual"}, {$inc: {balance: 20}})
  .run()
  .then(function(){
    //update is complete 
  })
  .catch(function(err){
    // Everything has been rolled back. 

    //log the error which caused the failure 
    console.log(err);
  });
Run Code Online (Sandbox Code Playgroud)

警告:任务当前没有被隔离(正在处理)因此,从技术上讲,两个任务可能只是因为MongoDB的工作原理而检索和编辑同一个文档.

它实际上只是教程站点上两阶段提交示例的通用实现:https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits/


jra*_*oyo 6

您可以通过在发生错误时手动回滚更改来模拟事务.在上面的示例中,如果另一个文档失败,只需删除已保存的文档.

您可以使用以下方法轻松完成Async:

    function rollback (doc, cb) {
      doc.remove(cb);
    }

    async.parallel([
          player.save.bind(player),
          story.save.bind(story),
      ],
      function (err, results) {
        if (err) {
          async.each(results, rollback, function () {
            console.log('Rollback done.');
          });
        } else {
          console.log('Done.');
        }
      });
Run Code Online (Sandbox Code Playgroud)

显然,回滚本身可能会失败 - 如果这是不可接受的,您可能需要重新构建数据或选择其他数据库.

注意:我在这篇文章中对此进行了详细讨论.


Joã*_*ero 5

Mongoose >= 5.2.0 和 MongoDB >= 4.0.0(带副本集)现在支持事务

https://mongoosejs.com/docs/transactions.html