I'm a little bit confused by the findAndModify
method in MongoDB. What's the advantage of it over the update
method? For me, it seems that it just returns the item first and then updates it. But why do I need to return the item first? I read the MongoDB: the definitive guide and it says that it is handy for manipulating queues and performing other operations that need get-and-set style atomicity. But I didn't understand how it achieves this. Can somebody explain this to me?

- 4,503
- 4
- 21
- 42

- 5,019
- 15
- 44
- 61
6 Answers
If you fetch an item and then update it, there may be an update by another thread between those two steps. If you update an item first and then fetch it, there may be another update in-between and you will get back a different item than what you updated.
Doing it "atomically" means you are guaranteed that you are getting back the exact same item you are updating - i.e. no other operation can happen in between.

- 41,784
- 5
- 109
- 133
-
8I'm still a little bit confused. How does `findAndModify` guarantee that there is no other update operation interfering with it? – chaonextdoor May 28 '12 at 04:44
-
86@chaonextdoor findAndModify acquires a lock to the database when it starts the operation so that no other operation can process when it is running. When it finishes the operation it releases the lock. – Lycha May 28 '12 at 09:28
-
4findAndModify doesn't actually obtain a lock until the modify part of request. So it is possible for multiple processes to be able to update the same record. – Mark Unsworth Mar 19 '13 at 17:28
-
3@MarkUnsworth incorrect. See https://github.com/mongodb/mongo/blob/master/src/mongo/db/commands/find_and_modify.cpp#L122 the writeLock is acquired for duration of operation. – Asya Kamsky Mar 20 '13 at 00:09
-
1We've seen issues at high load when using findAndModify to manage a job queue. The find looked for jobs with an active status of false and the modify command set the active status to true to prevent other processes from accessing the job, but several processes were actually able to process the same job at the same time. The processes were all running on separate machines so not a local threading issue – Mark Unsworth Apr 22 '13 at 16:48
-
6@MarkUnsworth open a support case with 10gen - if there is a bug in locking with findAndModify I can guarantee you engineers would want to fix it asap. If that was the case though we would see a lot of people report this behavior but findAndModify works as designed for pretty much everyone who is using it - cases where it seemed like it wasn't came down to logic or implementation bugs on the client side, but of course in complex software there can always be a bug. – Asya Kamsky Apr 30 '13 at 03:07
-
2Not sure if there was a ticket ever filed because https://github.com/mongodb/mongo/blob/master/src/mongo/db/commands/find_and_modify.cpp#L137 still reads `Lock::DBWrite` - it obtains only a write lock. – gvaish Mar 02 '14 at 22:20
-
Does findAndModify work for only 1 document? I want to findOneAndModify – quantumpotato Dec 27 '14 at 19:29
-
findAndModify by definition only works on a single document, but unless you need the modified document returned, you should simply use "update". – Asya Kamsky Dec 29 '14 at 16:35
-
does anyone know how much faster is Update compared to findAndModify? – Maria Jul 07 '15 at 15:55
-
that's not really a meaningful question - it depends on many things - in some cases it is not any faster, in other cases it may be orders of magnitude faster. – Asya Kamsky Jul 08 '15 at 00:33
-
@AsyaKamsky it sounds like it could still have been given a meaningful answer by you though. If there are examples of cases where it is not faster and examples of where it is, it would probably allow him to infer the specific answer within his own ambiguous context but also lead to a better understanding of the workings of both operations. – funkyeah Sep 17 '15 at 13:53
-
@funkyeah that's a separate question from this one, in any case, so probably belongs in a new question of its own. – Asya Kamsky Sep 17 '15 at 15:53
-
5@AsyaKamsky I was considering arguing with you but then realized you are correct so now I'm thinking I should apologize. Sorry! – funkyeah Sep 18 '15 at 16:30
-
2This doesn't answer the question. I think the other answers are much more useful (i.e. they explain the difference between findAndModify and update instead of simply explaining atomicity) – nonagon Aug 24 '17 at 17:09
-
the question already specifies that OP understands that findAndModify returns the document being updated, but update does not. They are asking how that is achieved (plus why such two mechanisms were provided). – Asya Kamsky Aug 26 '17 at 10:15
findAndModify
returns the document, update does not.
If I understood Dwight Merriman (one of the original authors of mongoDB) correctly, using update to modify a single document i.e.("multi":false} is also atomic. Currently, it should also be faster than doing the equivalent update using findAndModify
.

- 7,506
- 1
- 38
- 51

- 757
- 6
- 5
From the MongoDB docs (emphasis added):
By default, both operations modify a single document. However, the update() method with its multi option can modify more than one document.
If multiple documents match the update criteria, for findAndModify(), you can specify a sort to provide some measure of control on which document to update. With the default behavior of the update() method, you cannot specify which single document to update when multiple documents match.
By default, findAndModify() method returns the pre-modified version of the document. To obtain the updated document, use the new option. The update() method returns a WriteResult object that contains the status of the operation. To return the updated document, use the find() method. However, other updates may have modified the document between your update and the document retrieval. Also, if the update modified only a single document but multiple documents matched, you will need to use additional logic to identify the updated document.
Before MongoDB 3.2 you cannot specify a write concern to findAndModify() to override the default write concern whereas you can specify a write concern to the update() method since MongoDB 2.6.
When modifying a single document, both findAndModify() and the update() method atomically update the document.

- 22,122
- 12
- 111
- 127
-
1You could always specify write concern to update operation. In addition, since 3.2 (3.1.1 technically) you can specify write concern to findAndModify as well. https://jira.mongodb.org/browse/SERVER-6558 – Asya Kamsky Sep 30 '17 at 19:33
-
I have found that in MongDB 3.6, although the doc states `findAndModify()` by default modifies only one doc and `update()` can updates one or more doc, when I use an `arrayFilters`, `findAndModify()` updates all matches. Maybe it is a bug?? – WesternGun Feb 16 '18 at 14:18
-
There is no bug - arrayFilters allow you to update multiple array elements but they are still in a single document. – Asya Kamsky Aug 09 '18 at 08:18
One useful class of use cases is counters and similar cases. For example, take a look at this code (one of the MongoDB tests): find_and_modify4.js.
Thus, with findAndModify
you increment the counter and get its incremented
value in one step. Compare: if you (A) perform this operation in two steps and
somebody else (B) does the same operation between your steps then A and B may
get the same last counter value instead of two different (just one example of possible issues).

- 40,627
- 11
- 95
- 117
This is an old question but an important one and the other answers just led me to more questions until I realized: The two methods are quite similar and in many cases you could use either.
- Both
findAndModify
andupdate
perform atomic changes within a single request, such as incrementing a counter; in fact the<query>
and<update>
parameters are largely identical - With both, the atomic change takes place directly on a document matching the query when the server finds it, ie an internal write lock on that document for the fraction of a millisecond that the server confirms the query is valid and applies the update
There is no system-level write lock or semaphore which a user can acquire. Full stop. MongoDB deliberately doesn't make it easy to check out a document then change it then write it back while somehow preventing others from changing that document in the meantime. (While a developer might think they want that, it's often an anti-pattern in terms of scalability and concurrency ... as a simple example imagine a client acquires the write lock then is killed while holding it. If you really want a write lock, you can make one in the documents and use atomic changes to compare-and-set it, and then determine your own recovery process to deal with abandoned locks, etc. But go with caution if you go that way.)
From what I can tell there are two main ways the methods differ:
- If you want a copy of the document when your update was made: only
findAndModify
allows this, returning either the original (default) ornew
record after the update, as mentioned; withupdate
you only get aWriteResult
, not the document, and of course reading the document immediately before or after doesn't guard you against another process also changing the record in between your read and update - If there are potentially multiple matching documents:
findAndModify
only changes one, and allows you customize thesort
to indicate which one should be changed;update
can change all withmulti
although it defaults to just one, but does not let you say which one
Thus it makes sense what HungryCoder says, that update
is more efficient where you can live with its restrictions (eg you don't need to read the document; or of course if you are changing multiple records). But for many atomic updates you do want the document, and findAndModify
is necessary there.

- 6,508
- 3
- 27
- 16
We used findAndModify() for Counter operations (inc or dec) and other single fields mutate cases. Migrating our application from Couchbase to MongoDB, I found this API to replace the code which does GetAndlock(), modify the content locally, replace() to save and Get() again to fetch the updated document back. With mongoDB, I just used this single API which returns the updated document.

- 34
- 1