Any way to get the modified IDS from mongodb's bulk operations using mongoose?

点点圈 提交于 2021-01-26 06:06:37

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/34146212/any-way-to-get-the-modified-ids-from-mongodbs-bulk-operations-using-mongoose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!