🍃 MongoDB Tutorial

MongoDB findAndModify, findOneAndUpdate, findOneAndDelete & findOneAndReplace

Learn MongoDB's atomic find-and-modify style methods — findAndModify(), findOneAndUpdate(), findOneAndDelete(), and findOneAndReplace() — with returnNewDocument examples.

Find-and-Modify Methods

These methods find a document and change it in one atomic operation, optionally handing back either the pre- or post-update version of that document.

findAndModify()

Updates a single matching document and, by default, returns the document as it looked before the update.

db.employees.findAndModify({
  query: { empid: 202 },
  update: { $set: { age: 23 } }
})
// returns the OLD document — but the update did happen; re-run find() to confirm

Pass new: true to get the updated document back instead:

db.employees.findAndModify({
  query: { empid: 202 },
  update: { $set: { age: 24 } },
  new: true
})

findOneAndUpdate()

The modern equivalent of findAndModify() for updates. Same default behavior — returns the pre-update document unless returnNewDocument: true is passed.

db.employees.findOneAndUpdate(
  { empid: 202 },
  { $inc: { salary: 5000 } },
  { returnNewDocument: true }
)

findOneAndDelete()

Finds and deletes the first matching document in one step, returning the document that was deleted (or null if nothing matched).

db.employees.findOneAndDelete({ empid: 212 })
// returns the deleted document

db.employees.findOneAndDelete({ empid: 213 })
// null — no document with that empid existed

findOneAndReplace()

Replaces an entire matching document with a new one — unlike $set, this doesn't merge fields, it swaps the whole document (keeping only _id).

db.employees.findOneAndReplace(
  { empid: 204 },
  { salary: 20000, email: "pritygupta@gmail.com", phone: 4444444444, empid: 204 },
  { returnNewDocument: true }
)

If your replacement document is missing a field with a unique index (like email), MongoDB may throw a duplicate-key error trying to write null for it — always include your unique fields in the replacement document.

Common Errors & Troubleshooting

  • Confused why the "returned" document doesn't reflect your update — by default, all of these methods return the document as it was before the change; add new: true (for findAndModify) or returnNewDocument: true (for findOneAndUpdate) to see the post-update version.
  • findOneAndReplace() unexpectedly wiping out fields — a replace swaps the entire document body (except _id); any field you don't include in the replacement document is gone. Use findOneAndUpdate() with $set instead if you only want to change specific fields.
  • findOneAndDelete() returning null — this just means no document matched the filter; it's not an error, just an empty result.

Key Takeaways

  • All four methods combine "find" and "change" into a single atomic step — no separate find-then-update round trip.
  • By default they return the document as it was before the change; use new: true / returnNewDocument: true to get the updated version.
  • findOneAndReplace() swaps the whole document body, unlike findOneAndUpdate() which merges via operators like $set.