Update
Updating a document means finding it with a filter, then applying an update document that describes the change. MongoDB gives you updateOne(), updateMany(), and replaceOne() — each taking the same two-argument shape: (filter, update).
updateOne()
Updates the first document matching the filter. If more than one document matches, only one — the first found — is modified.
updateOne basics
const result = db.users.updateOne(
{ email: "alice@example.com" }, // filter
{ $set: { age: 29, active: true } } // update
)
result.matchedCount // 1 — documents that matched the filter
result.modifiedCount // 1 — documents actually changed
result.acknowledged // trueupdateMany()
Updating every matching document
const result = db.products.updateMany(
{ category: "widgets" },
{ $set: { onSale: true }, $inc: { views: 0 } }
)
result.matchedCount
result.modifiedCount // may be less than matchedCount if some already had onSale: true setmodifiedCount can be lower than matchedCount — MongoDB only counts a document as modified if the update actually changed its stored value. Setting a field to the value it already has does not count as a modification.replaceOne()
replaceOne() swaps the entire document (except _id) for a new one — it does not merge fields the way $set does. Any field not present in the replacement document is gone.
Whole-document replacement
db.users.replaceOne(
{ email: "alice@example.com" },
{ email: "alice@example.com", name: "Alice Chen", age: 29 }
// any fields the old document had that aren't listed here are dropped
)replaceOne() only when you intend to overwrite the whole document. For partial changes, use updateOne()/updateMany() with operators like $set — a common bug is calling replaceOne() with a partial object and silently losing every other field.$set and $unset — the Basics
Setting and removing fields
db.users.updateOne(
{ _id: 1 },
{
$set: { age: 30, "profile.bio": "Backend engineer" },
$unset: { legacyFlag: "" } // value on $unset is ignored, but must be present
}
)The upsert Option
Pass { upsert: true } and MongoDB will insert a new document built from the filter and update operators if nothing matched — instead of doing nothing.
Upsert — update if it exists, insert if it doesn't
db.counters.updateOne(
{ _id: "pageViews" },
{ $inc: { count: 1 } },
{ upsert: true }
)
// First call: no document matches → inserts { _id: "pageViews", count: 1 }
// Every call after: document exists → increments countupsert result fields
{
acknowledged: true,
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 1,
upsertedId: "pageViews"
}$setOnInsert alongside upsert: true to set fields only when the upsert actually creates a new document (e.g. a createdAt timestamp that shouldn't change on subsequent updates).Updating Nested Fields with Dot Notation
Reach into embedded documents and arrays with dot-notation field paths. Quote the whole path as a single string key — you can't write nested object literals for this in an update document.
Dot notation for nested updates
db.users.updateOne(
{ _id: 1 },
{ $set: { "address.city": "Vancouver", "address.postalCode": "V6B 1A1" } }
)
// Array elements by index
db.orders.updateOne(
{ _id: 42 },
{ $set: { "items.0.qty": 3 } } // updates the first item's qty
)arrayFilters — a Preview
When you need to update array elements that match a condition — not just a fixed index — use the $[identifier] positional operator together with arrayFilters. This is covered in depth on the Update Operators page.
Updating array elements that match a condition
db.orders.updateOne(
{ _id: 42 },
{ $set: { "items.$[el].shipped": true } },
{ arrayFilters: [{ "el.qty": { $gte: 2 } }] }
)
// Only array elements where qty >= 2 get shipped: trueReturning the Updated Document
updateOne()/updateMany() return a write result, not the document itself. To get the document back in the same round-trip, use findOneAndUpdate() with returnDocument: "after".
findOneAndUpdate to get the document back
const updated = db.users.findOneAndUpdate(
{ email: "alice@example.com" },
{ $inc: { loginCount: 1 } },
{ returnDocument: "after" }
)
// updated is the modified document itself, not a write-result objectExample Session
test> db.users.updateOne({ _id: 1 }, { $set: { age: 30 } })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
test> db.users.updateOne({ _id: 999 }, { $set: { age: 30 } }, { upsert: true })
{
acknowledged: true,
insertedId: null,
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 1,
upsertedId: 999
}updateOne()— modifies at most one matching document.updateMany()— modifies every matching document.replaceOne()— swaps the whole document (minus_id) for a new one.upsert: true— inserts a new document when nothing matches instead of doing nothing.findOneAndUpdate()— updates and returns the document in a single round-trip.