当前mongoose中的方法实现使用遗留的写入关注API来确定修改文档的数量。正如您所指出的,即使内容没有实际更改,例如不向集合添加新成员的
$addToSet
操作,也会返回修改后的计数。
只要您的MongoDB服务器版本足够新(需要MongoDB 2.6或更高版本),且mongoose版本足够新并捆绑了最新的mongodb驱动程序,则可以从
Bulk Operations 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 ) );
})
返回的"result"对象符合
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”事件。