Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Mongoose异步多个保存冲突_Javascript_Node.js_Mongodb_Mongoose_Socket.io - Fatal编程技术网

Javascript Mongoose异步多个保存冲突

Javascript Mongoose异步多个保存冲突,javascript,node.js,mongodb,mongoose,socket.io,Javascript,Node.js,Mongodb,Mongoose,Socket.io,我在使用Node/Mongoose/Socket.io时遇到了一个很大的逻辑问题。。。假设我得到了一个服务器模型,在我的应用程序中它经常同时被调用,有些调用涉及更新模型中的数据 db.Server.findOne({_id: reference.server}).exec(function(error, server) { catches.error(error); if (server !== null) { serve

我在使用Node/Mongoose/Socket.io时遇到了一个很大的逻辑问题。。。假设我得到了一个服务器模型,在我的应用程序中它经常同时被调用,有些调用涉及更新模型中的数据

    db.Server.findOne({_id: reference.server}).exec(function(error, server) {

        catches.error(error);

        if (server !== null) {

              server.anything = "ahah";

              server.save(function(error) { });

        }

    }
有时,两个人会同时调用它,而第一个人会保存()另一个人可能已经找到了“服务器”并得到了“旧对象”,但它不是最新的并保存()

这里最大的问题是,当第二个家伙将保存()这个“服务器”(旧对象)时,它将覆盖第一个的更改。。。您可以想象它将在我的应用程序上产生的巨大冲突

我曾考虑将所有save()方法改为update(),这样可以解决这个问题,但在项目的某个阶段,直接使用update()是非常棘手的,而且不太实际

有人在更新findOne()调用时,有没有办法“锁定”它?比如当你发现它时,你也会说“嘿,我会很快更新它,所以现在不要让别人发现它”(使用Mongoose,甚至MongoDb)

我已经搜索了一段时间,但没有找到任何答案:(


希望你能理解我的问题;)谢谢

正如您在这里看到的,这不是处理数据更新的最佳方式。如果你考虑你要做什么,本质上归结为:

  • 从数据库中获取对象
  • 在代码中更新属性
  • 将数据保存回原处,不保证有其他人修改了它
  • 因此,在可能的情况下,您需要避免这种模式,并遵循常识,即您只需要更改当前未设置为该值的现有值。因此,这意味着只需使用运算符(如
    $set
    )处理“更新”类型的语句:

    db.Server.findOneAndUpdate(
        { "_id": refernce.server, "anything": { "$ne": "ahah" } },
        { "$set": { "anything": "ahah" } },
        function(err,server) {
           if ( server != null ) {
    
              // then something was actually found and modified
              // so server now is the updated document
    
           }
        }
    );
    
    这意味着您将放弃mongoose的任何字段验证或其他保存钩子,但它是一种“原子”形式的更新,因为读和写不是单独的操作,这是您当前实现的方式

    如果您希望实现某种类型的“锁定”,那么类似的方法是最好的方法。因此,如果您想在文档上设置一个“状态”以显示有人正在编辑它,那么请维护一个字段来执行此操作,并将其构建到您的查询中

    要“阅读”文档并获取要呈现给“编辑”的信息,您可以执行以下操作:

    db.Server.findOneAndUpdate(
        { "$_id": docId, "locked": false },
        { "$set": { "locked": true } },
        function(err,document) {
    
        }
    );
    
    这意味着当有人“抓取”编辑时,随后的操作将无法这样做,因为他们要检索的文档的锁定状态是
    false
    ,而现在不再是。同样的原则适用于将编辑提交为“保存”时,正好相反:

    db.Server.findOneAndUpdate(
        { "$_id": docId, "locked": true },
        { "$set": { "locked": false } },
        function(err,document) {
    
        }
    );
    

    您始终可以执行更高级的操作,例如保存的修订,或者通过操作或任何其他形式的处理来期望版本号。但总的来说,你应该根据自己的需要来管理它

    我刚刚意识到我在stack overflow上发布了一篇类似的帖子。你可以在这里找到帖子:


    在这篇帖子里,有人告诉我要记住某个日期以避免这种行为。这就是我所做的,效果很好。但是,如果您使用多进程,则需要找到一种在进程之间共享内存的方法。

    否。看看你如何用mongo建立一个有人的网站。。。您可以构造模式,以便使用原子
    update
    调用完成所有文档修改。。。我仍然不明白Mongoose的目的是什么如果他们不能管理这种情况,save()系统是无用的,如果有两个人在做类似的事情,这肯定会发生在每个网站上。。。谢谢你的回复,我会把一切都重构;)请记住,Mongoose确实使用原子的
    update
    调用实现了
    save
    ,只调用了
    $set
    您实际更改的文档中的字段,因此它并不像您想象的那么糟糕。最麻烦的是数组操作(这就是Mongoose添加的原因),但无论如何,你都需要意识到发生了什么。最后一种解决方案的唯一问题是,如果另一个人真的需要在第一个人更改数据之后更改数据,那么“锁定”州政府将削减流程,这可能导致其他冲突。。无论如何,这是一个很好的技巧,我将更改代码并尝试以这种方式使用mongo;)