let dbOperations = Edge.collection.initializeOrderedBulkOp()
edges.forEach(edge => {
dbOperations.find({_id: edge.id}).upsert().updateOne({
$set: {
value: edge.value
},
$setOnInsert: {
_id: edge.id
}
})
})
dbOperations.execute()
.then(result => {
console.log(result.nModified) // This shows the number of edges that is actually modified
console.log(result.getModifiedIds()) // This is what I want to achieve
})
有任何方法可以达到这个目的吗?
答案 0 :(得分:2)
从一个观点来看,anwer是“不”,这是有充分理由的。
一般来说,MongoDB“更新”操作旨在跨越通常的“多个”文档,因此意味着符合条件的任何内容。所以这里的一般情况是你要么以单数形式要么更新,要么根据是否有任何匹配来更新或不更新。
在“批量”上下文中,大多数情况都适用,因为标准匹配与否,在这种情况下,您将分别获得nMatched
和nModified
的返回值,因为还有可能实际更新“匹配”文档,其中要修改的数据已经是作为修改目标的值。
nMatched
和nModified
之间的最后一个区别是“你无法可靠地执行此操作”的主要原因,因为并非必须修改所有匹配项。
但是,在识别“upsert”操作和实际“更新”之间,您可以创建 guestimate 值。由于所提到的区别,它不会100%精确,但基本过程是将输入列表与getUpsertedIds()
的返回值进行比较,这是一个有效的调用。
目前避开世界其他地方的ES6语法:
var upserted = result.getUpsertedIds(); // get this from the bulk result
upserted = upserted.map(function(up) { return up._id }); // filter out just the _id values
var modifiedIds = edges.map(function(edge) { // get _id only from source
return edge.id;
}).filter(function(edge) {
return upserted.indexOf(edge) == -1; // and return only non upserted
});
来自.getUpsertedIds()
的返回结果是一个对象数组,其中包含批量更新中的“索引”位置和“upsert”的生成或提供的_id
值。
[ { index: 0, _id: 1 } ]
因此,将输入列表与“upserted”列表进行匹配,以查看“what not there”,基本上会返回可能刚刚修改过的内容。当然需要注意的是,如果值已经与修改相同,那么它根本就不是修改。
但是由于API的工作原理,它与您将获得的一样接近。