Writing Data
Updates
An update changes part of a document with operators such as $set and $inc. To swap the whole document, see Replacements.
Update one or many
await users.updateOne(
{ email: "kage@example.com" },
{ $set: { name: "Kage" } },
);
await users.updateMany({ age: { $lt: 18 } }, { $set: { minor: true } });updateOne changes the first
matching document. updateMany
changes all of them.
Operators
| Operator | What it does |
|---|---|
$set | Sets fields, creating them if they're missing |
$unset | Removes fields |
$inc | Adds to a number. A missing field is set to the amount |
$min | Lowers a field to the value, if the value is smaller |
$max | Raises a field to the value, if the value is larger |
$push | Appends to an array, creating it if the field is missing |
$addToSet | Appends to an array unless an equal element is already there |
$pull | Removes every matching element from an array |
One update can use several operators:
await users.updateOne(
{ email: "kage@example.com" },
{
$set: { "address.city": "Osaka" },
$inc: { loginCount: 1 },
$max: { lastSeen: new Date() },
$addToSet: { tags: "beta" },
$unset: { resetToken: true },
},
);Dotted paths reach into nested documents. TypeScript only lets each operator target fields of the right type: $inc only accepts number fields, and $push only array fields.
The result
const result = await users.updateMany(
{ active: false },
{ $set: { archived: true } },
);
result.matchedCount; // documents the filter matched
result.modifiedCount; // documents that actually changedmodifiedCount only counts documents whose stored data changed. Setting a field to the value it already has matches the document but doesn't modify it.
Upsert
With upsert: true, an update that matches nothing inserts a new document instead. It starts from the equality conditions in the filter, then the update is applied to it:
const result = await counters.updateOne(
{ name: "page-views" },
{ $inc: { value: 1 } },
{ upsert: true },
);
result.upsertedId; // the new _id, or null if a document matchedThe first call inserts { name: "page-views", value: 1 }. Later calls increment it.
Rules
_idcan't be changed. Updates can't target_id.- Each command is atomic. An
updateManychanges every matching document or none: if one document can't be updated, nothing is. - Commands don't form transactions. Two separate updates can be interleaved with other clients' writes.
- Not supported yet:
$mul,$rename,$pop, positional operators like$, and update pipelines. The server rejects them withInvalidUpdate.
The update type is UpdateFilter, and the result is UpdateResult.