MongoDBUpdate Operators Reference

Update Operators

Update operators are the vocabulary you use inside the second argument of updateOne()/updateMany() to describe what changes, as opposed to a full document replacement. This page catalogs the field, array, and pipeline update operators you'll reach for constantly.

Field Update Operators

Operator

Effect

$set

Sets a field to a value, creating it if it does not exist

$unset

Removes a field entirely

$inc

Increments (or decrements, with a negative value) a numeric field

$mul

Multiplies a numeric field by a given value

$rename

Renames a field

$min

Sets the field only if the given value is less than the current value

$max

Sets the field only if the given value is greater than the current value

$currentDate

Sets a field to the current date/time

$set / $unset

$set and $unset

JS
db.users.updateOne(
  { _id: 1 },
  {
    $set: { status: "active", "profile.title": "Engineer" },
    $unset: { tempFlag: "" }
  }
)
$inc / $mul

Atomic increment and multiply

JS
// Increment (or decrement with a negative number)
db.products.updateOne({ sku: "WIDGET-42" }, { $inc: { stock: -1, viewCount: 1 } })

// Multiply — e.g., apply a 10% price increase across a category
db.products.updateMany({ category: "widgets" }, { $mul: { price: 1.10 } })
Tip
$inc is atomic at the document level — safe for concurrent counters like view counts or inventory decrements without a separate read-modify-write cycle.
$rename

Renaming a field across a collection

JS
db.users.updateMany({}, { $rename: { "username": "handle" } })
Warning
$rename only renames a field if it exists on that document. It's a schema-level change applied per document — run it with an empty filter ({}) to apply it across an entire collection, and expect it to be slow on large collections since every document is rewritten.
$min / $max

Conditional set — only if the new value wins

JS
// Only updates if 3 is less than the current "lowestPrice"
db.products.updateOne({ sku: "WIDGET-42" }, { $min: { lowestPrice: 3 } })

// Only updates if the new score is higher than the current "highScore"
db.leaderboard.updateOne({ userId: 7 }, { $max: { highScore: 9800 } })
$currentDate

Timestamping an update

JS
db.sessions.updateOne(
  { _id: "sess_123" },
  { $currentDate: { lastActivity: true, "meta.lastModifiedTs": { $type: "timestamp" } } }
)
// lastActivity → BSON Date
// meta.lastModifiedTs → BSON Timestamp (internal type — Date is almost always what you want)
Array Update Operators

Operator

Effect

$push

Appends a value (or values, with $each) to an array

$pull

Removes all array elements matching a condition

$addToSet

Appends a value only if it is not already present

$pop

Removes the first (-1) or last (1) element of an array

$push, $addToSet, $pull, $pop

JS
// $push — append one or more values
db.posts.updateOne({ _id: 1 }, { $push: { tags: "mongodb" } })
db.posts.updateOne({ _id: 1 }, { $push: { tags: { $each: ["nosql", "database"] } } })

// $addToSet — append only if not already present (a "set" semantics)
db.posts.updateOne({ _id: 1 }, { $addToSet: { tags: "mongodb" } })   // no-op if already there

// $pull — remove every element matching a condition
db.posts.updateOne({ _id: 1 }, { $pull: { tags: "deprecated" } })
db.orders.updateOne({ _id: 1 }, { $pull: { items: { qty: { $lt: 1 } } } })

// $pop — remove the last (1) or first (-1) element
db.queue.updateOne({ _id: 1 }, { $pop: { pending: 1 } })   // removes the last element
The Positional $ Operator

The positional $ operator updates the first array element that matched the query filter, without needing to know its index.

Update the first matching array element

JS
// Mark the first item with sku "WIDGET-42" as shipped
db.orders.updateOne(
  { _id: 42, "items.sku": "WIDGET-42" },
  { $set: { "items.$.shipped": true } }
)
Warning
The positional $ operator only affects the first matching element, even if several elements in the array match the filter. Use $[] (all elements) or $[identifier] with arrayFilters to affect more than one.
$[] — Update All Array Elements

Update every element in an array

JS
// Apply a 5% discount to every item in every order
db.orders.updateMany({}, { $mul: { "items.$[].price": 0.95 } })
$[identifier] and arrayFilters

When you need to update only the array elements that match a condition, use a named identifier in the update path and describe that condition separately in arrayFilters.

Conditional array element updates

JS
// Mark only the line items with qty >= 2 as bulk-eligible
db.orders.updateOne(
  { _id: 42 },
  { $set: { "items.$[el].bulkEligible": true } },
  { arrayFilters: [{ "el.qty": { $gte: 2 } }] }
)

// Multiple identifiers can target nested array levels independently
db.students.updateOne(
  { _id: 1 },
  { $set: { "grades.$[g].scores.$[s].verified": true } },
  {
    arrayFilters: [
      { "g.subject": "Math" },
      { "s.value": { $gte: 90 } }
    ]
  }
)
Pipeline Updates

Since MongoDB 4.2, the update argument can be an aggregation pipeline (an array of stages) instead of a plain update document. This unlocks computing a new field's value from other fields in the same document — something plain $set alone cannot do in one operator (short of $expr-adjacent tricks).

Pipeline update — derive a field from other fields

JS
db.orders.updateMany(
  {},
  [
    { $set: { total: { $sum: "$items.price" } } },
    { $set: { totalWithTax: { $multiply: ["$total", 1.13] } } }
  ]
)
// Each stage can reference fields set by a previous stage in the SAME pipeline update
Note
Pipeline-style updates only support a subset of aggregation stages: $set/$addFields, $unset, $replaceRoot/$replaceWith, and $project. You cannot use $match, $group, or $lookup inside an update pipeline.
  • $set / $unset — the everyday field mutators.

  • $inc / $mul — atomic numeric changes, safe under concurrency.

  • $push / $addToSet / $pull / $pop — array mutation.

  • $[] and $[identifier] with arrayFilters — target multiple or conditional array elements.

  • Pipeline updates (array form) — compute a field from other fields in the same update.