【问题标题】:How to control multiple update in one collection field in mongo and javascript?如何在 mongo 和 javascript 中控制一个集合字段中的多个更新?
【发布时间】:2018-04-09 09:40:24
【问题描述】:

假设我有一个文档

{
  maxCountAllowed:100,
  currentCount:99
}

我有一个 API,如果 currentCount 还不是 100,用户调用它来增加它..

if(document.currentCount < document.maxCountAllowed){
    document.currentCount ++;
    document.save();
}else{
    console.log("sorry maximum count reached");
}

假设有 2 个或更多用户同时调用 API .. 他们都会发现 currentCount 仍然是 99,因此函数将继续执行,他们都会将 currentCount 增加到 101 或更多..我怎样才能防止这样的事情? 即使他们两个都将其设为 100,我仍然希望他们中的一个能够更新,而另一个得到错误消息。

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    Mongo 提供了文档级别的原子性,如下所述:https://docs.mongodb.com/v3.4/tutorial/update-documents/#behavior 这意味着如果对一个对象有两个并发更新操作,那么它们将连续执行。

    更新操作也支持 $inc 操作符:https://docs.mongodb.com/manual/reference/operator/update/inc/#up._S_inc

    最后一部分是 $where 运算符:https://docs.mongodb.com/manual/reference/operator/query/where/#examples 请记住,它的性能不如使用常量查询。

    因此您可以只更新符合要求的文档:

    db.products.update(
      { $where : "this.currentCount < this.maxCountAllowed" },
      { $inc: { currentCount: 1 } }
    );
    

    然后检查操作的结果,看看是否有任何更新。

    【讨论】:

    • 因此,如果同一文档中有 2 个并发更新,它们将同步发生。其中一个将更新文档,而另一个将更新 0 个文档?
    • Mongo 会依次处理它们,并且只有其中一个会更新文档。
    【解决方案2】:

    您可以在数据库上执行此操作作为带有附加查询条件的更新。所以首先你必须获取你的文件才能知道限制。那么假设你的文档的_id等于1,那么你就可以执行这样的更新:

    db.yourCollection.update({_id: 1, currentCount: {$lt: 100}}, { $inc: { currentCount: 1 } });
    

    $inc 将进行增量,但前提是文档的当前状态的 currentCount 字段的值小于 100,这是您在本文档的另一个字段中定义的限制。

    【讨论】:

    • 所以在这种情况下,只有其中一个会增加它,而其他人不会在 console.log 的部分中收到消息,但会出现 mongo 错误..我说得对吗?跨度>
    • 不,将会有一个空更新,因为您的所有文档都不符合指定条件。如果要检索修改的文档,也可以检查 updateAndModify。
    【解决方案3】:

    我认为你所说的情况永远不会发生。想象一下同时有 2 个请求,它们都会得到 99/100 的结果。然后他们都会尝试更新到 100/100。您正在增加从节点脚本中的数据库获得的值,而不是直接在 mongo 中的值。

    您也可以使用db.collection.findAndModify,但似乎没有用于此的 mongoose API。

    https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/

    【讨论】:

    • OK .. 即使是 100 我仍然无法返回 1 个用户,他更新了它,而其他用户在 console.log 部分收到一条消息
    • 那你应该试试findAndModify方法。检查这个关于如何与猫鼬一起使用它的问题:stackoverflow.com/questions/7334390/…
    猜你喜欢
    • 1970-01-01
    • 2019-12-31
    • 2016-07-20
    • 2019-02-16
    • 1970-01-01
    • 2022-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    相关资源
    最近更新 更多