Skip to content

MongoDB - Update Document

This tutorial covers the modern methods for modifying documents in MongoDB: updateOne(), updateMany(), and replaceOne(). We will also discuss powerful update operators and the ‘upsert’ option. The older update() and save() methods are now deprecated.

To modify fields within a document, you must use update operators. These are special keywords prefixed with a $ that define how to change the data.

  • $set: Sets the value of a field. If the field does not exist, it will be created.
  • $inc: Increments the value of a numeric field by a specified amount.
  • $unset: Removes a specified field from a document.
  • $push: Adds an element to an array.
  • $pull: Removes all instances of a value from an array.

This method updates a single document that matches the specified filter. Even if multiple documents match, only the first one found will be updated.

db.COLLECTION_NAME.updateOne(
<filter>,
<update>,
<options>
);

Let’s update a user’s profile in a users collection.

// Initial document:
// { _id: 1, name: "Alice", status: "active", logins: 5 }
db.users.updateOne(
{ name: "Alice" }, // Filter
{ // Update
$set: { status: "active_pro" },
$inc: { logins: 1 }
}
);
// Result:
// { "acknowledged": true, "matchedCount": 1, "modifiedCount": 1 }

This method updates all documents that match the filter.

Imagine we need to archive all blog posts published before 2020.

db.posts.updateMany(
{ year: { $lt: 2020 } }, // Filter: posts with year less than 2020
{ $set: { status: "archived" } } // Update
);
// Result (if 50 posts were updated):
// { "acknowledged": true, "matchedCount": 50, "modifiedCount": 50 }

This method replaces the entire content of a single document with a new one, except for the immutable _id field. Note: This method does not accept update operators ($set, $inc, etc.).

// Original document: { _id: 1, name: "Alice", status: "active" }
db.users.replaceOne(
{ name: "Alice" },
{ name: "Alice Smith", status: "inactive", reason: "Migrated to new system" }
);
// New document: { _id: 1, name: "Alice Smith", status: "inactive", ... }

All update methods accept an upsert option. When set to true, if no document matches the filter, a new document is created based on the filter and update expressions. This is extremely useful for ‘update or insert’ logic.

// Tries to update settings for 'user456'. If they don't exist, create them.
db.userSettings.updateOne(
{ userId: "user456" },
{ $set: { theme: "dark", notifications: true } },
{ upsert: true }
);

As seen in the Atomicity chapter, findOneAndUpdate() is a special-purpose method that updates a single document and returns it in the same operation. By default, it returns the document before the update. You can set the option { returnNewDocument: true } to get the document after the update.

The update() method is deprecated. Its behavior was confusing because by default it only updated one document, requiring { multi: true } to update many. This is now clearly separated into updateOne() and updateMany().

The save() method is also deprecated. It was a wrapper that would either update a document if an _id was present or insert it if not. This functionality is better and more explicitly handled by replaceOne(), updateOne(), or using the upsert: true option.