Skip to main content

CRUD Operations - Updating Documents

Now that you've learned how to create and read documents in MongoDB, it's time to master updating existing data. In this lesson, you'll learn how to modify documents using various update methods and operators.

Learning Goals:

  • Use updateOne() and updateMany() to modify documents
  • Understand and apply update operators like $set, $inc, and $push
  • Replace entire documents with replaceOne()
  • Handle upsert operations for create-or-update scenarios

Update Methods Overview

MongoDB provides several methods for updating documents, each serving different use cases:

  • updateOne(): Updates a single document that matches the filter
  • updateMany(): Updates all documents that match the filter
  • replaceOne(): Replaces an entire document (except _id)
  • findOneAndUpdate(): Finds a document and updates it, returning the document

Basic Update Operations

Updating a Single Document

The updateOne() method takes two parameters: a filter to find the document, and an update operation specifying what to change.

update-single.js
// Update a user's email address
db.users.updateOne(
{ username: "alice" },
{ $set: { email: "alice.new@email.com" } }
);

Updating Multiple Documents

Use updateMany() when you need to apply the same change to multiple documents.

update-multiple.js
// Give all inactive users a welcome bonus
db.users.updateMany(
{ status: "inactive" },
{
$set: {
status: "active",
welcomeBonus: true
}
}
);

Update Operators

MongoDB provides powerful update operators to perform specific modifications.

$set - Modify Fields

The $set operator updates or adds specific fields without affecting other fields in the document.

set-operator.js
// Update specific fields in a product
db.products.updateOne(
{ _id: 101 },
{
$set: {
price: 29.99,
inStock: true,
lastUpdated: new Date()
}
}
);

$inc - Increment Numeric Values

The $inc operator increments or decrements numeric values.

inc-operator.js
// Increment view count and decrement inventory
db.articles.updateOne(
{ _id: 201 },
{
$inc: {
views: 1,
inventory: -1
}
}
);

$push and $addToSet - Array Operations

Add elements to arrays with $push (allows duplicates) or $addToSet (prevents duplicates).

array-operators.js
// Add a tag to an article (allows duplicates)
db.articles.updateOne(
{ _id: 301 },
{ $push: { tags: "javascript" } }
);

// Add a category (prevents duplicates)
db.articles.updateOne(
{ _id: 301 },
{ $addToSet: { categories: "programming" } }
);
tip

Use $addToSet when you want to maintain unique values in an array, similar to a set data structure.

Document Replacement

Sometimes you need to replace an entire document while keeping the same _id. Use replaceOne() for this purpose.

replace-document.js
// Replace a user's entire profile
db.users.replaceOne(
{ username: "bob" },
{
username: "bob",
email: "bob.new@company.com",
role: "admin",
createdAt: new Date("2023-01-15"),
lastLogin: new Date()
}
);
warning

replaceOne() replaces the entire document except for the _id field. Any fields not included in the replacement document will be lost!

Upsert Operations

An "upsert" either updates an existing document or inserts a new one if no document matches the filter.

upsert-example.js
// Update user settings or create if doesn't exist
db.userSettings.updateOne(
{ userId: "user123" },
{
$set: {
theme: "dark",
notifications: true,
language: "en"
}
},
{ upsert: true } // This enables upsert behavior
);

Working with Embedded Documents

Update operations work seamlessly with embedded documents and arrays of documents.

embedded-update.js
// Update a specific field in an embedded document
db.products.updateOne(
{ "sku": "WIDGET-001" },
{ $set: { "details.weight": "2.5kg" } }
);

// Update an element in an array of embedded documents
db.orders.updateOne(
{ "_id": 501, "items.productId": 101 },
{ $set: { "items.$.quantity": 3 } }
);

Common Pitfalls

  • Forgetting $set: Using { field: value } instead of { $set: { field: value } } will replace the entire document
  • Accidental field deletion: When using replaceOne(), ensure you include all required fields
  • Unintended upserts: Only use { upsert: true } when you actually want to create new documents
  • Performance with large arrays: Frequent $push operations on large arrays can impact performance
  • Missing array filters: Use array filters when updating specific elements in arrays based on complex conditions

Summary

You now know how to update MongoDB documents effectively:

  • Use updateOne() for single documents and updateMany() for multiple documents
  • Apply update operators like $set, $inc, and $push for specific modifications
  • Replace entire documents with replaceOne() when needed
  • Implement upsert operations for create-or-update scenarios
  • Work with embedded documents and arrays
Show quiz
  1. Which method would you use to add a new field to multiple documents without affecting existing fields?

  2. What's the difference between $push and $addToSet when working with arrays?

  3. What happens if you use updateOne() with a filter that matches no documents and { upsert: true }?

  4. Why should you be careful when using replaceOne() instead of update operations with $set?


Answers:

  1. updateMany() with the $set operator - this allows you to add new fields to all matching documents while preserving existing data.

  2. $push always adds the element to the array (allowing duplicates), while $addToSet only adds the element if it doesn't already exist in the array (preventing duplicates).

  3. MongoDB will create a new document using the filter criteria as the basis for the new document, combined with the update operations specified.

  4. replaceOne() replaces the entire document (except _id), which means any fields not included in the replacement document will be permanently deleted from that document.