MongoDB $set Stage

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $set?

$set is a MongoDB aggregation stage that adds new fields or overwrites existing ones using expressions. Other fields stay on the document. It is an alias for $addFields.

Remember
$set = add or overwrite fields, keep the rest

{ $set: { <field>: <expression>, ... } }

keeps all existing fields
same name → overwrites that field
alias for $addFields (same behavior)

vs $project → reshape / pick fields
not the update operator $set
UsePrefer
Add or overwrite fields$set (or $addFields)
Slim / reshape output$project
Remove fields$unset

How to Use $set in MongoDB

Name the fields, give each an expression, and place the stage where later steps need those values.

  1. Start (or continue) an aggregation pipeline with aggregate([...]).
  2. Add { $set: { fieldName: <expression> } }.
  3. Use field paths like "$price" and operators like $multiply.
  4. Use the new or updated fields in later stages.
PieceRequired?Role
Field nameYesNew (or replaced) key on the document
ExpressionYesLiteral, field path, or aggregation expression
Multiple fieldsNoSet several keys in one stage

Pseudocode

Pseudocode
for each document:
    out = copy(document)          // keep existing fields
    for each (field, expression) in $set:
        out[field] = evaluate(expression)   // add or overwrite
    emit out

Cheat Sheet

Keep these facts handy while setting fields in a pipeline.

TopicDetail
TypeAggregation stage (not find / not update $set)
Syntax{ $set: { <field>: <expression> } }
Alias$addFields (same behavior)
DefaultKeeps all existing fields
Same nameOverwrites that field
Nested fieldsDot path: "address.city"
vs $projectAdditive vs reshape

Live Preview

Watch $set add salePrice = price × 0.9 while keeping the original fields.

Simulates $set: { salePrice: { $multiply: ["$price", 0.9] } }.

Result
input:
  { name: "Mug", price: 20, status: "draft" }

$multiply → 20 * 0.9 = 18

output (+ keeps original fields):
  { name: "Mug", price: 20, status: "draft", salePrice: 18 }

Worked Walkthrough — Sale Price

One product has price: 20 and status: "draft". Goal: add salePrice without dropping other fields.

Calculation
Document in:
  { name: "Mug", price: 20, status: "draft" }

$set:
  salePrice: { $multiply: ["$price", 0.9] }

20 * 0.9 = 18

Document out:
  {
    name: "Mug",
    price: 20,
    status: "draft",
    salePrice: 18      // new
  }

MongoDB Examples

We use a small products collection. First add a sale price, then overwrite status and add the sale price together. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine three products with a name, price, and draft status.

mongosh
db.products.insertMany([
  { _id: 1, name: "Mug", price: 20, status: "draft" },
  { _id: 2, name: "Notebook", price: 10, status: "draft" },
  { _id: 3, name: "Bag", price: 40, status: "draft" }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps three documents in products. Run find() to see them:

mongosh
db.products.find()

Read each document like this:

Field in MongoDBExamplePlain English
name"Mug"Product name
price20List price
status"draft"Current listing state

How It Works

  1. Insert once. insertMany adds three product documents to products.
  2. Fields stay as written. Price is a number; name and status are strings.
  3. find() shows the same shape. Ready for $set next.

Example 2 — Add salePrice

Goal: append salePrice = price × 0.9 on every product without removing other fields.

mongosh
db.products.aggregate([
  {
    $set: {
      salePrice: { $multiply: ["$price", 0.9] }
    }
  }
]);

How It Works

  1. Read stored price. Mug has price: 20 from Example 1.
  2. Compute the expression. $multiply returns 18.
  3. Keep everything else. $set appends salePrice; name and status stay.

Example 3 — Overwrite Status

Set status to "listed" (overwrite) and add salePrice in the same stage.

mongosh
db.products.aggregate([
  {
    $set: {
      status: "listed",
      salePrice: { $multiply: ["$price", 0.9] }
    }
  }
]);

How It Works

  1. Same stored documents. Still using the three products from Example 1.
  2. Overwrite by name. status: "listed" replaces "draft".
  3. Add a new field. salePrice is computed and appended.
  4. Pipeline only. This does not write back to the collection unless you add a write stage later.

Edge Cases & Pitfalls

Check these before using $set in production pipelines.

overwrite

Same name replaces the field

If you write price: { $multiply: ["$price", 1.1] }, the old price is gone. Use a new name when you need both values.

update

Not the update operator

Aggregation $set does not persist changes by itself. Update $set is a different operator used with updateOne / updateMany.

shape

Not a slim reshape tool

To drop unused fields for an API response, follow with $project or $unset.

alias

$addFields is the same stage

$addFields is an alias. Pick one style and stay consistent in a codebase.

Performance Notes

ApproachCostBest for
$set alonePer-document expressionsA few computed or updated fields
$match then $setFewer docs to computeLarge collections
Late $project / $unsetTrim after computeSlim API responses

Expression work is usually cheap compared with large sorts or joins. Filter early with $match when only some documents need the new fields.

Key Takeaways

  • Role: add or overwrite fields; keep the rest.
  • Alias: same as $addFields.
  • vs $project: additive vs reshape.
  • Caution: not the update operator $set.

One line: $set answers “set these fields on every document—and leave the rest alone.”

Frequently Asked Questions

$set adds new fields to documents or overwrites existing field values using aggregation expressions. All other fields stay unless you assign to the same name.
Yes. $set is an alias for $addFields—they share the same syntax and behavior. Use whichever name reads clearer in your pipeline.
$project reshapes the document—you choose which fields appear. $set is additive: every existing field remains unless you overwrite it.
Yes. If you set a field name that already exists, the new expression replaces the old value.
No. This page covers the aggregation stage $set. The update operator $set changes documents with updateOne/updateMany. Same name, different context.
$unset removes fields from documents. Add computed values with $set, then drop temporary fields with $unset if needed.

Next: $skip

Skip a number of documents in an aggregation pipeline.

$skip tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful