Updating Documents
Neuromancer sells out, then six copies arrive. You do not want to rewrite the whole book document just to change one number, and you certainly do not want two cashiers overwriting each other's counts. Update operators change exactly the fields you name.
The rule
Name the target, then say the change with an operator: $set, $inc, $push.
db.books.updateMany({ stock: { $lt: 5 } }, { $set: { reorder: true } })
// matchedCount: 2 (Neuromancer with 0, The Hobbit with 3)
db.books.updateOne({ _id: 2 }, { $inc: { stock: 6 } })
// { acknowledged: true, matchedCount: 1, modifiedCount: 1, upsertedId: null, ... }The common operators:
| Operator | Does | Example |
|---|---|---|
$set |
sets a field, creating it if missing | { $set: { price: 7.5 } } |
$unset |
removes a field | { $unset: { signed: "" } } |
$inc |
adds to a number (negative to subtract) | { $inc: { stock: -1 } } |
$push |
appends to an array | { $push: { genres: "space" } } |
$addToSet |
appends only if not already present | { $addToSet: { genres: "classic" } } |
$pull |
removes matching array elements | { $pull: { genres: "myth" } } |
- updateOne changes the first match; updateMany changes every match.
- Dotted paths work:
{ $set: { "publisher.country": "GB" } }. { upsert: true }as a third argument inserts a new document when nothing matches.- replaceOne(filter, newDoc) swaps the whole document, keeping only
_id. - The legacy
update()method is deprecated; use these.
The shortcut
Read the result like a receipt: matchedCount = how many the filter found; modifiedCount = how many actually changed.
First run
updateOne({ _id: 1 }, { $addToSet: { genres: "space" } }): Dune matches and gains "space". matched 1, modified 1.
The trap: updateOne({ _id: 2 }, { stock: 6 }) with no operator. mongosh rejects it because an update needs operators; and replaceOne with that document would erase the title, price and everything else.
Drills
Answer fast — trust the rule.
Which update sells one copy of Emma safely?
updateMany({ genres: "fantasy" }, { $set: { shelf: "F" } }) reports which matchedCount?
You $set Circe's price to 12, which it already is. What is modifiedCount?
What does { upsert: true } do when the filter matches nothing?
Which call removes the signed field from The Hobbit?
Remember
- Name the target, then say the change with an operator.
- Shortcut: matchedCount is what the filter found, modifiedCount is what really changed.
- Trap: an update with no operators is rejected, and replaceOne wipes every field you leave out.
