MongoDBupdateOne, updateMany & replaceOne

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

JS
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    // true
updateMany()

Updating every matching document

JS
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 set
Note
modifiedCount 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

JS
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
)
Warning
Use 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

JS
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

JS
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 count

upsert result fields

JS
{
  acknowledged: true,
  matchedCount: 0,
  modifiedCount: 0,
  upsertedCount: 1,
  upsertedId: "pageViews"
}
Tip
Use $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

JS
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

JS
db.orders.updateOne(
  { _id: 42 },
  { $set: { "items.$[el].shipped": true } },
  { arrayFilters: [{ "el.qty": { $gte: 2 } }] }
)
// Only array elements where qty >= 2 get shipped: true
Returning 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

JS
const updated = db.users.findOneAndUpdate(
  { email: "alice@example.com" },
  { $inc: { loginCount: 1 } },
  { returnDocument: "after" }
)
// updated is the modified document itself, not a write-result object
Example 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.