【问题标题】:Mongodb update $pull always return 1Mongodb 更新 $pull 总是返回 1
【发布时间】:2014-10-02 08:49:39
【问题描述】:

我想使用这个查询从数组中删除一个嵌入对象。 它工作正常,但结果始终为 1。无论是否拉出数组元素。 这使得很难以适当的方式响应请求。

db.clients.update({_id: someId}, {$pull: {someArray: {id: req.params.id}}}, function(err, result) {
  if (err) return next(err);
  res.json(result);
});

Q) 有没有办法让这个查询在没有拉取元素时返回 null 或零?

【问题讨论】:

    标签: node.js mongodb mongodb-query


    【解决方案1】:

    虽然 MongoDB 2.6 中发生了一些变化,但大多数驱动程序使用的实现仍然是“遗留”的写入关注操作,该操作是从名称稍不恰当的 .getLastError() 调用中获得的。

    这里的一个已知问题是,只要更新语句“匹配”文档,那么无论操作是否实际修改了文档,所获得的结果都将等于“匹配”的数量。因此,诸如 $pull$addToSet 之类的操作实际上可能不会对通过“拉”查询的元素不存在或已经存在的文档内容执行任何操作为“addToSet”而存在。

    WriteResult 在 shell 中可用(实际上现在在所有驱动程序中),但这是混淆步骤的地方。在驱动程序和 shell 中实现的 .update() 命令不在事实相同。在 shell 中,这个方法实际上封装了 "Bulk Operations API" 方法,并且在连接到有能力的服务器时会尝试使用这些方法,并且只有在服务器没有能力时才回退到旧实现。

    因此,您目前需要在您的应用程序中构建相同类型的逻辑,或者只是忍受您的应用程序可能永远不会真正连接到低于 2.6 版本的服务器节点并专门使用批量 API 方法:

    db.collection('testcol',function(err,col) {
      if (err) throw err;
    
      var bulk = col.initializeOrderedBulkOp();
    
      bulk.find({ "_id": someId}).updateOne({ 
          "$pull": { 
              "someArray": { "id": req.params.id }
           }
      });
      bulk.execute(function(err,result) {
        if (err) throw err;
        console.log( result.toJSON() );
      });
    });
    

    所以这就是现代 MongoDB 版本的 shell 方法“幕后”发生的事情。返回的“写入结果”将准确反映匹配的文档数和“修改”数。因此,如果实际上没有任何更改,则“已修改”包含 0。

    但您必须直接使用这些方法。除非其他人想在更高级别的 API 上提供与 shell 现在相同的抽象,否则原始方法不会更改以保持向后兼容性。

    【讨论】:

    • 谢谢尼尔!你怎么知道这一切?谷歌对此一无所知。你是真正的 MongoDB Avatar。
    • @AndersÖstman 最好的判断方法是在函数末尾不带括号()db.collecition.update 之类的简单操作。这基本上记录了函数内容,在 shell 中只是 JavaScript。
    • 这很好用! 如果我使用普通的 mongodb 模块...它不适用于 Mongoskin。
    • @AndersÖstman 你这么说很有趣。正如我已经知道您正在使用先前问题中的 mongoskin 并在该环境下运行上面的代码。你不能用这种类型的操作对 mongoskin 做的是使用一个“集合”,它按名称声明它允许你做什么。不过,使用与我上面相同的语法,一切正常。这就是从底层节点驱动程序中提取真正的“集合”对象的方式。但是,基于“promise”的 mongoskin API 不会对预先声明的集合名称执行此操作。
    • 你又是对的!是所有批量操作方法都更“正确”和最新,还是只是这种差异很重要的更新情况?在大多数情况下,我认为返回整个 writeResult 比只包含部分 writeResult 的苗条结果更好,这在大多数 CRUD 方法中似乎都是这种情况。
    【解决方案2】:

    您使用的是哪个 mongo 版本?对于 2.6 版,更新返回一个带有更新操作状态的 WriteResult 对象,如您在 mongo documentarion

    中所见

    【讨论】:

    • 我使用的是 2.6。我知道 writeResult 对象。我已经通过在回调中命名它来检查它,例如:function(err, result, writeResult)。不幸的是,无论是否拉出数组元素,此对象都没有区别。
    • 你有没有尝试将更新的返回分配给一个变量并检查它,像这样:var result = db.clients.update({...});
    • 我没有。尽管这似乎是一种奇怪的处理方式,但我明天会试试这个。
    猜你喜欢
    • 2014-08-10
    • 2014-06-01
    • 1970-01-01
    • 2016-11-21
    • 2019-10-10
    • 2014-04-13
    • 2017-03-20
    • 2013-11-04
    • 2011-12-09
    相关资源
    最近更新 更多