Updating Multiple Documents with updateMany()

The updateMany() method applies an update to every document matching the supplied filter.

Basic example

db.products.updateMany(
  { category: "electronics" },
  { $set: { taxable: true } }
);

Every matching document receives the specified update.

Update all documents deliberately

An empty filter matches all documents:

db.products.updateMany(
  {},
  { $set: { reviewed: true } }
);

This is a valid operation, but it can modify the entire collection. Always verify that this is the intended behavior before running a broad update.

Update nested fields

db.users.updateMany(
  { "address.country": "India" },
  { $set: { "address.region": "South Asia" } }
);

Dot notation updates the nested region field without replacing the entire address document.

Increment matching documents

db.products.updateMany(
  { category: "books" },
  { $inc: { stock: 10 } }
);

Every matching document receives the increment.

Understand the result

An acknowledged update result typically provides:

  • matchedCount: the number of documents matching the filter.
  • modifiedCount: the number of documents actually modified.
  • upsertedCount: the number of documents inserted through upsert behavior, if enabled.
  • upsertedId: the identifier of an upserted document when applicable.

A matched document does not necessarily count as modified. If the update produces no change, matchedCount may exceed modifiedCount.

Multi-document atomicity

updateMany() is not a single atomic operation across every matching document. Other operations may observe partial progress, and an error can occur after some documents have been modified.

If the business requirement demands that several document changes succeed or fail together, evaluate a transaction supported by your deployment and workload. Transactions introduce additional costs and should not be used without understanding the consistency requirement.

Safe operational workflow

  1. Run a find query with the intended filter.
  2. Inspect representative matching documents.
  3. Estimate how many documents will be affected.
  4. Run the update in a suitable environment.
  5. Inspect matchedCount and modifiedCount.
  6. Verify the resulting documents.
An empty filter can update the entire collection

Before running updateMany({}, ...), verify that modifying every document is intentional. Test broad migrations in a non-production environment and use an appropriate recovery plan.

Update a group of documents
db.updateManyDemo.insertMany([
  { name: "Keyboard", category: "electronics", stock: 10 },
  { name: "Monitor", category: "electronics", stock: 5 },
  { name: "Book", category: "books", stock: 20 }
]);

// Inspect targets before updating.
db.updateManyDemo.find({ category: "electronics" });

const result = db.updateManyDemo.updateMany(
  { category: "electronics" },
  { $set: { taxable: true } }
);

printjson({
  matchedCount: result.matchedCount,
  modifiedCount: result.modifiedCount
});

db.updateManyDemo.find({ category: "electronics" });
💡 The operation updates all electronics documents. The result distinguishes documents that matched from documents that actually changed. Inspect the filter before running a broad update, particularly in production.
Key Takeaways
  • updateMany() modifies all documents matching the filter.
  • An empty filter matches all documents in the collection.
  • matchedCount and modifiedCount measure different things.
  • A multi-document update is not atomic as a whole.
  • Inspect and validate the target set before broad updates.
Knowledge Check

Why can matchedCount be greater than modifiedCount?