I have a document I want to upsert. It has a unique index on one of the properties, so I have something like this to ensure I get no collisions
var barVal = 1;
collection.UpdateOne(
x=>x.Bar == barVal,
new UpdateDefinitionBuilder<Foo>().Set(x=>x.Bar, barVal),
new UpdateOptions { IsUpsert = true });
But I seem to sometimes get collisions from this on the unique index on bar.
Is mongo atomic around upserts, so if the filter matches the document cant be changed before the update completes?
If it is I probably have a problem somewhere else, if its not I need to handle the fact its not.
The docs don't seem to sugguest that this is one way or the other.
https://docs.mongodb.com/v3.2/reference/method/Bulk.find.upsert/ https://docs.mongodb.com/v3.2/reference/method/db.collection.update/
Upsert is not atomic. This is insinuated by the Mongo documentation: https://docs.mongodb.org/v3.0/reference/method/db.collection.update/. To avoid inserting the same document more than once, only use upsert: true if the query field is uniquely indexed.
The basic upsert function has been enhanced to support an Atomic upsert capability. This enhancement permits Teradata TPump to perform single‑row upserts in a single pass. This one‑pass logic adopts the upsert‑handling technique used by MultiLoad.
Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.
Pattern. In MongoDB, a write operation on a single document is atomic. For fields that must be updated together, embedding the fields within the same document ensures that the fields can be updated atomically.
Upsert is a combination of insert and update (inSERT + UPdate = upsert). We can use the upsert with different update methods, i.e., update, findAndModify, and replaceOne. Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter.
In MongoDB, a write operation is atomic on the level of a single document, even if the operation modifies multiple embedded documents within a single document. When a single write operation (e.g. db.collection.updateMany ()) modifies multiple documents, the modification of each document is atomic, but the operation as a whole is not atomic.
Note: To prevent MongoDB from inserting the same document more than once, create a unique index on the name field. With a unique index, if multiple documents want the same update with upsert: true, only one update operation successfully inserts a new document. db.Collection_name.update ( {Selection_criteria}, {$set: {Update_data}}, {
Or in other words, upsert is a combination of update and insert (update + insert = upsert). If the value of this option is set to true and the document or documents found that match the specified query, then the update operation will update the matched document or documents.
Actually, docs says something about this. Here is what I found in db.collection.update#use-unique-indexes
To avoid inserting the same document more than once, only use
upsert: true
if the query field is uniquely indexed....
With a unique index, if multiple applications issue the same update with
upsert: true
, exactly oneupdate()
would successfully insert a new document.The remaining operations would either:
update the newly inserted document, or
fail when they attempted to insert a duplicate. If the operation fails because of a duplicate index key error, applications may retry the operation which will succeed as an update operation.
So, if you have created a unique index on the field you are querying, it is guaranteed that the insertion is "atomic" and a sort of rollback is performed if a failure occures.
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