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
})
Any way to achieve this?
Well from one point of view the anwer is "no" and there is a very good reason for that.
Generally speaking, MongoDB "update" operations are intended to work across what is commonly "multiple" documents, therefore meaning whatever matched the criteria. So the general case here is whatever you either asked to be updated in either singular or by selection was either updated or not depending on whether anything was matched.
In the "Bulk" context, much of the same thing applies, in that there was either a criteria match or not, in which case you will get returned values for nMatched
and nModified
repectively, as there is also the possibility that a "matched" document is not actually updated where the data present to be modified is already the value which is the target of the modification.
That last distinction between nMatched
and nModified
is the prime reason why "you cannot reliably do this", since not everything matched is necessarily modified.
You can however make a guestimate value in the case of discerning between "upsert" actions and actual "updates". It won't be 100% acurate because of the noted distintion, but the basic process is to compare your input list to the returned value from getUpsertedIds()
, which is a valid call.
Eschewing the ES6 syntax for the rest of the world at present:
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
});
Where the returned result of from .getUpsertedIds()
is an array of objects containing both the "index" position from the bulk update and the generated or supplied _id
value of the "upsert".
[ { index: 0, _id: 1 } ]
So matching out your input list against the "upserted" list to see "what is not there", basically returns things that where probably just modified. With of course the caveat that if the value was already the same as the modification, then it really was not a modification at all.
But due to how the API is meant to work, that's as close as you are going to get.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With