following answers from here and here, attempting to implement a bulk upsert operation using Mongoose 5.4
Have something like so:
const update = await Company.bulkWrite([
{
'updateOne': {
'filter': { 'url': result.url },
'update': {
testVal: 'testinggg'
},
'upsert': true,
}
},
]);
When I run this, I see the following response:
{
ok: 1,
writeErrors: [ ],
writeConcernErrors: [ ],
insertedIds: [ ],
nInserted: 0,
nUpserted: 0,
nMatched: 1,
nModified: 1,
nRemoved: 0,
upserted: [ ]
}
However, the entry is not actually updated.
If I change the filter so it checks for something and thus needs to create a new entry instead of updating, it works fine. But if the filter property matches and it needs to update, no updates are made to the matching document.
Have also tried using $set but to no avail:
const update = await Company.bulkWrite([
{
'updateOne': {
'filter': { 'url': result.url },
'update': {
'$set': {
testVal: 'testinggg'
}
},
'upsert': true,
}
},
]);
What am I doing wrong here?
2
Answers
Needed to create an explicit UNIQUE index against the property I was filtering on.
I find the problem statement presented in the question as well as the resolution noted in the answer pretty misleading. This answer will attempt to clarify some additional context that is important for overall understanding of this situation for future readers.
To suggest that the provided code wasn’t updating the database is incorrect. The response from the database that was helpfully provided in the question description shows us that directly via:
Specifically that tell us that the first document the command processed matched the query criteria, did not have the requested
testVal
, and was therefore modified accordingly. In other words, theupdateOne
command did just as expected – it updated one document in the collection.The ‘answer’ that was mentioned was creating a
unique
index on theurl
field. But this action did not suddenly make theupdateOne
or the wrappingbulkWrap
itself behave any differently. Instead that action constrains what data can be present in the collection in the first place. The command will still attempt to update up to one document, but now only a maximum of one document could possibly match the query condition.Taken together, we can deduce that what was originally happening is that there were multiple documents in the collection with the value for the
url
field that was being tested. It was those other documents that were getting updated (one at a time) when testing as opposed to a different one (with the sameurl
) that was being checked.It’s perfectly acceptable from a business logic perspective to enforce the
unique
constraint (or not), but doing such just changes what data is present rather than ‘fixing’ the command that appeared to not be performing updates.As a side note I’d mention that there is nothing in the question description that suggest a bulk operation is needed here. If you didn’t have the
unique
constraint and wanted to modify all matching documents then you could useupdateMany
directly. Similarly if you want to modify many documents with differenturl
s with the same change (eg settingtestVal
field), then you could also useupdateMany
with the$in
operator for specifying the query condition. It is only in the case that you want to modify documents with differenturl
values each in different manners all in a single database request that you would need to use the bulk wrapper.