【问题标题】:Handling concurrent modification w/ mongoose使用猫鼬处理并发修改
【发布时间】:2016-05-31 12:30:18
【问题描述】:

我的应用程序中有几个地方使用了 mongoose,我需要在这些地方处理并发修改。

我知道我的所有文档中都有一个版本“__v”。我看到的大部分内容都指向这个博客:

http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning

其中概述了使用 __v 字段来防止文档中的并发数组修改。即:

posts.update({ _id: postId, __v: versionNumber }
           , { $set: { 'comments.3.body': updatedText }})

mongoose 是否在保存文档时以任何方式自动使用 __v 字段来验证文档?还是您总是必须将其添加到您的查询语句中?

【问题讨论】:

  • mongoose.set("debug",true) 会为您解答您的问题。并不是说我无论如何都喜欢这个过程。测试__v 的特定值意味着您已经从文档中获得了该信息,并且如果该值/版本不同,您根本无法修改内容。这几乎是不现实的,实际上您的应用程序不应该关心这一点,或者应该以不同的方式应用更新,其中需要“历史”之类的东西。即添加到数组。如果您设计了正确的访问模式,那么您将不会遇到此类问题。
  • 上述代码中的快速示例。你应该从不comments.3.body暗示更新数组中那个索引位置的“body”。相反,您应该写.update({ "_id": postId, "comments._id": commentId },{ "$set": { "comments.$.body": updatedText } })。这样一来,除了您知道自己真正想要的元素之外,您永远不会更新任何东西,而不是现在可能处于该位置的其他东西。 __v 唯一能帮助的就是避免两个用户同时更改相同的评论。但最好只允许作者进行更改。

标签: node.js mongodb mongoose


【解决方案1】:

查看Mongoose源代码,__v确实只用于arraysVERSION_WHERE是在updating the array path时设置的。

  if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {
    self.$__.version = VERSION_INC;
  }
  // now handling $set, $unset
  else if (/\.\d+\.|\.\d+$/.test(data.path)) {
    // subpath of array
    self.$__.version = VERSION_WHERE;
  }

根据this answer

var t = Test();
t.name = 'hi'
t.arr = [1, 2, 3, 4, 5, 6];

 t.save(function (err, result) {
    console.log(result);
    // use Mongoose pull method on the array
    t.arr.pull(3);
    t.save(function(err2, result2) {
        console.log(result2)
    });
});

结果:

 { __v: 0,
  name: 'hi',
  _id: 53f59d2a6522edb12114b98c,
  arr: [ 1, 2, 3, 4, 5, 6 ] }
{ __v: 1,
  name: 'hi',
  _id: 53f59d2a6522edb12114b98c,
  arr: [ 1, 2, 4, 5, 6 ] }

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 2012-07-30
    • 1970-01-01
    • 2016-05-05
    • 2014-10-17
    • 2018-11-24
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多