MongoDB:更新计数错误

MongoDB: incorrect update count

本文关键字:错误 更新 MongoDB      更新时间:2023-09-26

在我的数据库中,我有一个名为'fruits'的字段,这是一个简单的数组。在此数组中插入元素时,我使用$addToSet仅插入此数组中不存在的元素。

我想知道我插入的元素是否真的修改了这个字段。然而,回调中的docModified参数总是返回1,即使我试图添加一个已经存在的元素

model.update (
    { username: username }, // find the document
    { $addToSet : { fruits: "apple" } }, // add "apple" to fruits field
    function (err, docModified) {
        console.log(docModified);
        // !PROBLEM: this will print "1" no matter what
    }
);

有人知道为什么吗?非常感谢!(顺便说一句,我用的是Mongoose)

当前mongoose中的方法实现使用遗留的写关注点API来确定修改文档的计数。正如您所注意到的,即使没有对内容进行实际更改,例如 $addToSet 操作没有向集合添加新成员,也将返回修改后的计数。

只要你的MongoDB服务器版本是最近的(需要是MongoDB 2.6或更高),你的mongoose版本是最近的,并且捆绑了最近的MongoDB驱动程序,那么你可以从批量操作API响应中获得正确的数字。

要使用mongoose完成此操作,您需要调用模型上的.collection访问器,它返回本机驱动程序集合对象:

var bulk = Model.collection.initializeOrderedBulkOp();
bulk.find({ username: username })
    .updateOne({ $addToSet : { fruits: "apple" } });
bulk.execute(function(err,result) {
    if (err) throw err;
    console.log( JSON.stringify( result, undefined, 4 ) );
})

返回的"结果"是一个符合BulkWriteResult()规范的对象,它或多或少看起来像这样:

{
   "writeErrors" : [ ],
   "writeConcernErrors" : [ ],
   "nInserted" : 2,
   "nUpserted" : 0,
   "nMatched" : 3,
   "nModified" : 3,
   "nRemoved" : 1,
   "upserted" : [ ]
}

但是,具体来说,当您使用$addToSet并且成员已经存在时,响应将包含"nMatched": 1"nModified": 0,这是您想要看到的结果,确认实际上没有添加到集合中。

在MongoDB 2.6 shell中,所有的更新和插入方法都尝试使用这个API,当它可用时,只有在连接到旧服务器时才回退到旧的实现。所以,如果你在一个现代的shell和一个现代的服务器上这样做,你会看到相同的结果。

希望mongoose本身也会被修改为在可用的情况下使用这些方法,并提供对相同响应的访问。这似乎是未来的方式,但代码库还没有赶上并利用它。

注意:在访问集合对象后使用任何本机驱动程序方法时要注意的一件事是确保在调用mongoose时具有与数据库的活动连接。Mongoose通过将任何请求排队直到实际建立连接来隐藏这一点。

因此,如果您直接使用集合对象方法,那么您可能需要确保在该代码执行之前等待连接上的"open"事件。

"number受影响的是文档更新的数量,即使新值相同。这直接来自蒙古。"我从这个论坛帖子:https://github.com/LearnBoost/mongoose/issues/867

这意味着你必须想出一种不同的方法来确定元素在更新之前是否从数组中丢失。我建议在更新之前提取所有文档并遍历它们。很明显,这并不理想,但我认为没有别的办法了。