MongoDB Update

MongoDB's update operations let you modify existing documents in place using updateOne, updateMany, and update operators like $set, without ever replacing a whole document unless you choose to.

updateOne(): Modifying a Single Document

db.collection.updateOne(filter, update) finds the first document matching filter and applies update to it. The update argument is not the new document itself — it's an object of update operators describing what should change. The most common operator, $set, replaces the value of specific fields while leaving everything else in the document untouched.

Update a single matching document

db.products.updateOne(
  { sku: 'ABC-123' },
  { $set: { price: 24.99, inStock: true } }
)

updateMany(): Modifying Every Match

updateMany() takes the same two arguments but applies the update to every document that matches the filter, not just the first one. This is the tool you reach for when a change needs to apply across a whole segment of data — for example, marking every order from a cancelled batch as 'cancelled', or applying a price adjustment to an entire product category.

Update every document that matches the filter

db.products.updateMany(
  { category: 'clearance' },
  { $set: { discounted: true } }
)

Understanding the Result Object

Both methods return a result object rather than the updated document itself. matchedCount tells you how many documents satisfied the filter, and modifiedCount tells you how many were actually changed as a result. These can differ — if a document already had price set to 24.99, it would be matched but not modified, since there was nothing to change.

  • matchedCount — documents that satisfied the filter
  • modifiedCount — documents whose data actually changed
  • upsertedId — set only when upsert: true caused an insert
  • acknowledged — whether the write was acknowledged by the server

Upserts: Update or Insert

Passing { upsert: true } as a third argument tells MongoDB to insert a new document built from the filter and update if nothing matched the filter at all. This is handy for 'create or update' logic — for example, incrementing a daily visit counter for a page that might not have a document yet.

Insert a new document if no match is found

db.pageViews.updateOne(
  { page: '/pricing' },
  { $set: { lastVisited: new Date() } },
  { upsert: true }
)
Note: $set only touches the fields you name — it will never silently wipe out the rest of the document, which is the key difference between an update and a full document replacement.
Note: Careful: forgetting the update operator and passing a plain document as the second argument to updateOne() (instead of one wrapped in $set) will throw an error in modern MongoDB drivers, since a bare document is only valid for a full replacement via replaceOne().
MethodDocuments affectedReturns new/updated doc?
updateOne(filter, update)First match onlyNo — returns a result summary
updateMany(filter, update)All matchesNo — returns a result summary
updateOne(..., { upsert: true })Match, or a new insertNo, but upsertedId is included
findOneAndUpdate(filter, update)First matchYes — returns the document

Exercise: MongoDB Update

If you call updateOne(filter, { name: 'Sam' }) with no $ operator, what happens?