Atomic replace operation for mongo document - mongodb

I'm setting up a python application which uses mongodb (through pymongo).
I need to overwrite the contents of an entire document. This can be done either with update or replace. However, the mongo documentation isn't explicit about the atomicity of these operations - saying only that individual write operations are atomic, without explaining if update or replace use multiple write operations.
Does anyone know for sure if either of these operations is completely atomic?

find_and_modify is deprecated in the pymongo driver. Instead use one of:
find_one_and_delete
find_one_and_replace
find_one_and_update
The original find_and_modify had the potential to modify multiple documents which is probably not what was intended and is also not atomic.
For a truly ACID compiant sequence of modifications in MongoDB please look at MongoDB ACID Transactions. Supported since MongoDB 4.0, released last year.

Related

Difference between findOneAndDelete() and findOneAndRemove()

I am not able to differentiate findOneAndDelete() And findOneAndRemove() in the mongoose documentaion.
Query.prototype.findOneAndDelete()
This function differs slightly from Model.findOneAndRemove() in that
findOneAndRemove() becomes a MongoDB findAndModify() command, as
opposed to a findOneAndDelete() command. For most mongoose use cases,
this distinction is purely pedantic. You should use
findOneAndDelete() unless you have a good reason not to.
TLDR: You should use findOneAndDelete() unless you have a good reason not to.
Longer answer:
From the Mongoose documentation of findOneAndDelete:
This function differs slightly from Model.findOneAndRemove() in that findOneAndRemove() becomes a MongoDB findAndModify() command, as opposed to a findOneAndDelete() command. For most mongoose use cases, this distinction is purely pedantic. You should use findOneAndDelete() unless you have a good reason not to.
Mongoose Docs findOneAndDelete
In MongoDB native client (Mongoose is different) passing { remove: true } to findAndModify makes it remove the found document, it's behavior in this case would appear quite similar to findOneAndDelete.
However, there are some differences when using other options:
findAndModify takes 5 parameters :query, sort, doc (the update object), options and a callback. findOneAndDelete only takes 3 (filter or query, options and a callback)
options for findAndModify include w, wtimeout and j for write concerns, as:
“the level of acknowledgment requested from MongoDB for write operations to a standalone mongod or to replica sets or to sharded clusters.“ or simply guarantee levels available for reporting the success of a write operation.
options for findOneAndDelete do not include write concerns configuration.
findAndModify lets you return the new document and remove it at the same time.
Example:
// Simple findAndModify command returning the new document and
// removing it at the same time
collection.findAndModify({b:1}, [['b', 1]], {$set:{deleted: Date()}}, {remove:true}, calback)
Both of them are almost similar except findOneAndRemove uses findAndModify with remove flag and time complexity will be a bit higher compare to findOneAndDelete because you are doing an update. Delete are always faster.
In mongoose findOneAndDelete works the same way as findOneAndRemove. They both look an object by its properties in JSON, then goes ahead to delete it and as well as return it object once after deletion. When you are using the native mongodb as your database findOneAndDelete might be useful to you, but in the case of mongoose it is deprecated I may advise you to use findOneAndDelete to perform your operation based on the latest mongoose and nodejs configuration as at this period. https://github.com/Automattic/mongoose/issues/6880
Here is the exact difference (quoted from the mongoose docs in Model.findOneAndDelete() section):
"This function differs slightly from Model.findOneAndRemove() in that
findOneAndRemove() becomes a MongoDB findAndModify() command, as
opposed to a findOneAndDelete() command. For most mongoose use cases,
this distinction is purely pedantic. You should use findOneAndDelete()
unless you have a good reason not to."
Here is the link to it:
https://mongoosejs.com/docs/api.html#model_Model.findOneAndDelete
The other answers here have a lot of wrong info. They are for all intents and purposes the same, and you should just use findOneAndDelete().
Mongoose's Model.findOneAndRemove(query) becomes MongoDB's findAndModify({query, remove: true}).
Mongoose's Model.findOneAndDelete() becomes MongoDB's findOneAndDelete(). However, the MongoDB driver converts findOneAndDelete(query, opts) to findAndModify({query, remove: true}) (src). Thus they do the exact same thing in the database.
Both take the same options.
Both return the deleted document.
findOneAndRemove returns the removed document so if you remove a document that you later decide should not be removed, you can insert it back into the db. Ensuring your logic is sound before removing the document would be preferred to checks afterward IMO.
findOneAndDelete has the sort parameter which can be used to influence which document is updated. It also has a TimeLimit parameter which can control within which operation has to complete
I would suggest you use findOneAndDelete().
Mongoose provides both the features to handle data using the ORM and also features to write directly into the database, with findOneAndDelete() being one of the latter. Writing to database directly is more dangerous as you run the risk of not calling middleware or validators, potentially submitting partial or incomplete data to the database. Note that I said it's more dangerous, not that it's flat out dangerous, findOneAndDelete() just goes throughout the ORM adding safety.

MongoKitten batch update is atomic or not?

In Vapor MongoKitten there is an update method which accept array of documents. Is update atomically executed or it is method only for convenient use? MongoDB doc says:
When a single write operation modifies multiple documents, the
modification of each document is atomic, but the operation as a whole
is not atomic and other operations may interleave.
https://docs.mongodb.com/manual/core/write-operations-atomicity/
I'm assuming you're pointing towards the update(bulk method for multiple update queries. This function executes a single batch query with multiple update statements. Each update is executed separately but they are submitted in a single batch to MongoDB to limit network load and increase app performance. It's primarily intended for migrations, although there sure are other use cases.
EDIT: For the record, this is true for MongoKitten 4. The upcoming MongoKitten 5 release may not support this in the initial version of the high level APIs.

MongoDB. Transaction?

I wanted to know if there are ACID guarantees in multi-document transactions in MongoDB. What's the current status, existing materials are quite old. What's been upgraded now?
How can we simulate to show that it can't, if it can't OR can, if it can?
MongoDB will add support for multi-document transactions starting from version 4.0, so you will have ACID guarantees in multi-document transactions.
For details visit this link:
https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb?jmp=community
To make muti-document write process atomic You can use $isolated Operator
Using the $isolated operator, a write operation that affects multiple documents can prevent other processes from interleaving once the write operation modifies the first document. This ensures that no client sees the changes until the write operation completes or errors out.
You can perform Two Phase Commits for transaction-like semantics.
Check MongoDB 3.2 documentation for more details.

How to lock a Collection in MongoDB

I have a collection in my database
1.I want to lock my collection when the User Updating the Document
2.No operations are Done Expect Reads while Updating the collection for another Users
please give suggestions how to Lock the collection in MongoDB
Best Regards
GSY
MongoDB implements a writer greedy database level lock already.
This means that when a specific document is being written to:
The User collection would be locked
No reads will be available until the data is written
The reason that no reads are available is because MongoDB cannot do a consistent read while writing (darn you physics, you win again).
It is good to note that if you wish for a more complex lock, spanning multiple rows, then this will not be available in MongoDB and there is no real way of implementing such a thing.
MongoDB locking already does that for you. See what operations acquire which lock and what does each lock mean.
See the MongoDB documentation on write operations paying special attention to this section:
Isolation of Write Operations
The modification of a single document is always atomic, even if the write operation modifies >multiple sub-documents within that document. For write operations that modify multiple >documents, the operation as a whole is not atomic, and other operations may interleave.
No other operations are atomic. You can, however, attempt to isolate a write operation that >affects multiple documents using the isolation operator.
To isolate a sequence of write operations from other read and write operations, see Perform >Two Phase Commits.

Does findAndModify effectively lock the document to prevent update conflicts?

What type of locking does findAndModify() offer? Is is a write lock only, or read/write? Does it prevent simultaneous updates on the same record?
MongoDB has a global (per-instance) write lock, which serializes all updates across all data in the server (though different servers in a sharded cluster will each have their own independent locks). This means that at any given instant in time, only one update is taking place on any document, and therefore only one update for any given document.
findAndModify doesn't do anything different in this regard than an ordinary update -- it just returns the document to you.
According to the MongoDB docs for MongoDB: findAndModify() for under MongoDB: Atomic Operations it should be.