Data rarely stays still: prices change, stock levels move, users edit their profiles. MongoDB modifies documents in place with updateOne, updateMany, and a family of update operators that let you change exactly the fields you need without rewriting the whole document. This CodeYourCraft lesson walks through the operators you will use every day, plus upserts and findOneAndUpdate.
Both methods take a filter (which documents) and an update document (what to change). updateOne modifies the first match; updateMany modifies all matches:
use shop
db.products.updateOne(
{ name: 'Desk Lamp' },
{ $set: { price: 1399 } }
)
// { matchedCount: 1, modifiedCount: 1 }
db.products.updateMany(
{ tags: 'clearance' },
{ $set: { onSale: true } }
)The result distinguishes matchedCount from modifiedCount: a document that already had price 1399 would match but not be modified. Update documents must use operators; passing a plain document to updateOne is an error, which protects you from accidentally replacing an entire document.
db.customers.updateOne(
{ email: 'arjun@example.com' },
{
$set: { 'address.city': 'Mumbai', tier: 'gold' }, // create or overwrite
$unset: { legacyCode: '' }, // remove a field
$rename: { loyaltyPoints: 'points' } // rename a field
}
)$set creates fields that do not exist yet, including nested paths, which makes it the workhorse of schema evolution.
Counters and prices should be changed atomically on the server, never read-modify-written from the client:
db.products.updateOne({ _id: 'SKU-1001' }, { $inc: { 'stock.warehouse': -1 } })
db.products.updateMany({ tags: 'audio' }, { $mul: { price: 0.9 } }) // 10% off
db.products.updateOne({ _id: 'SKU-1001' }, { $min: { price: 449 } }) // only lowers
db.products.updateOne({ _id: 'SKU-1001' }, { $max: { highestBid: 700 } })Because each update is atomic per document, two simultaneous $inc operations never lose an increment.
db.products.updateOne({ _id: 'SKU-1001' }, { $push: { reviews: { user: 'Neha', stars: 5 } } })
db.products.updateOne({ _id: 'SKU-1001' }, { $addToSet: { tags: 'bestseller' } }) // no duplicates
db.products.updateOne({ _id: 'SKU-1001' }, { $pull: { tags: 'clearance' } }) // remove matchesTo update one element inside an array, the positional operator $ refers to the first element matched by the filter:
db.products.updateOne(
{ 'reviews.user': 'Neha' },
{ $set: { 'reviews.$.stars': 4 } }
)With upsert: true, MongoDB inserts a new document when the filter matches nothing, combining the filter fields with the update operators:
db.counters.updateOne(
{ _id: 'pageviews' },
{ $inc: { total: 1 } },
{ upsert: true }
)This one-liner initializes the counter on first use and increments it forever after, with no race conditions.
When you need the document back in the same atomic step, use findOneAndUpdate with returnDocument: 'after' to receive the updated version. It is the standard tool for job queues and sequence generators.
In the next lesson we complete CRUD by learning to delete documents safely.