Javascript MongoDB:更新计数不正确

Javascript MongoDB:更新计数不正确,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,在我的数据库中,我有一个名为'fruits'的字段,它是一个简单的数组。在该数组中插入元素时,我使用$addToSet仅插入该数组中不存在的元素 我想知道我插入的元素是否真的修改了这个字段。但是,回调中的docModified参数始终返回1,即使我尝试添加已存在的元素时也是如此 model.update ( { username: username }, // find the document { $addToSet : { fruits: "apple" } }, // ad

在我的数据库中,我有一个名为'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)

“受影响的数量是更新的文档数量,即使新值相同。这直接来自mongo。”我从这个论坛帖子中得到:

这意味着在更新之前,您必须想出一种不同的方法来确定数组中是否缺少元素。我建议在更新之前提取所有文档并遍历它们。显然这并不理想,但我认为没有其他方法可以做到这一点


希望这能有所帮助。

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

只要您的MongoDB服务器版本足够新(需要是MongoDB 2.6或更高版本),并且您的mongoose版本足够新,并且绑定了最新的MongoDB驱动程序,那么您就可以从响应中获得正确的数字

要使用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 ) );
})
返回的“结果”是符合规范的对象,大致如下所示:

{
   "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本身也能改变,在可用的情况下使用这些方法,并提供对相同响应的访问。这似乎是未来的发展方向,但代码库尚未赶上并利用这一点

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


因此,如果您直接使用collection对象方法,那么您可能希望确保在代码执行之前,您正在等待连接上的“open”事件。

直接来自mongo的是mongoose仍然实现的“legacy”响应。但是几个月来,已经有了一种确定正确响应的方法,因为它在底层驱动程序中实现了。非常感谢!非常有用且详细的回答:)