The Replacement Trap — update() without Operators
db.users.update({ name: "Alice" }, { status: "active" })
db.users.updateOne({ name: "Alice" }, { $set: { status: "active" } })
db.users.replaceOne(
{ name: "Alice" },
{ name: "Alice", status: "active", email: "alice@example.com" }
)
updateOne() vs replaceOne() — Key Differences
| Feature | updateOne() | replaceOne() |
| Primary Action | Modifies specific fields within a document | Substitutes the entire document with a new one |
| Existing Fields | Keeps unmentioned fields unchanged | Removes all existing fields except _id |
| Update Operators | Requires operators: $set, $inc, $push etc. | Cannot contain update operators — plain doc only |
| Network Traffic | Lower — sends only the changed fields | Higher — sends the entire new document |
| Concurrency Safety | Atomic field-level; safer under concurrent writes | Risk of lost updates if two clients race on read-modify-replace |
| Use Case | Patching / updating specific attributes | Complete structural overhaul of a record |
TIPPrefer updateOne() with $set for partial updates — it is safer, uses less bandwidth, and avoids accidentally wiping fields. Use replaceOne() only when you hold a complete, final version of the document and want the DB record to exactly match it.
Cannot Update _id
db.users.updateOne({ _id: 1 }, { $set: { _id: 2 } })
Nested Field Update on null Parent
db.users.updateOne({ _id: 1 }, { $set: { "address.city": "Mumbai" } })
db.users.updateOne({ _id: 1 }, { $set: { address: {} } })
db.users.updateOne({ _id: 1 }, { $set: { "address.city": "Mumbai" } })
NaN Behavior with $inc
db.data.updateOne({ _id: 1 }, { $inc: { value: 1 } })
db.data.updateOne({ _id: 1 }, { $set: { value: 0 } })
db.data.updateOne({ _id: 1 }, { $inc: { value: 1 } })
updateMany() Partial Failure
const session = db.getMongo().startSession()
session.startTransaction()
try {
db.getSiblingDB("mydb").orders.updateMany(
{ status: "pending" },
{ $set: { status: "processing" } },
{ session }
)
session.commitTransaction()
} catch(e) {
session.abortTransaction()
} finally {
session.endSession()
}
WARNA { status: null } filter in updateMany() targets documents where status is explicitly null AND documents where status is missing — this is the null/missing gotcha that can accidentally modify more docs than expected.