upsert, replaceOne и удаление
Три приёма: вставить-если-нет (upsert), заменить документ целиком и удалить ненужное.
upsert — режим обновления, при котором документ создаётся, если ни один не подошёл под фильтр.
upsert: обнови или вставь
Частая задача: «если запись есть — обнови, если нет — создай». Без upsert пришлось бы сначала проверять наличие, потом решать, что делать. Опция { upsert: true } делает это одним запросом:
db.counters.updateOne(
{ _id: "visits" },
{ $inc: { value: 1 } },
{ upsert: true }
)Если счётчика visits нет — MongoDB создаст документ с этим _id и применит $inc (значение станет 1). Если есть — просто увеличит. В ответе при вставке появится upsertedId:
Результат:
{
"acknowledged": true,
"matchedCount": 0,
"modifiedCount": 0,
"upsertedId": "visits"
}Upsert особенно полезен для счётчиков, кешей и синхронизации данных из внешних источников, где нет уверенности, существует ли запись.
replaceOne — полная замена
Иногда нужно именно заменить документ целиком, а не точечно поправить поля. Для этого есть честный replaceOne — он заменяет всё содержимое (кроме _id), но без операторов:
db.products.replaceOne(
{ _id: "SKU-1001" },
{ name: "Кофе молотый", price: 520, inStock: true }
)Все прежние поля документа исчезнут, останется новый объект. Используйте replaceOne сознательно: когда действительно хотите переписать запись, а не дополнить.
Удаление: deleteOne и deleteMany
deleteOne удаляет первый подходящий документ, deleteMany — все подходящие. Синтаксис фильтра — как в find:
db.users.deleteOne({ name: "Анна" })
db.users.deleteMany({ inStock: false })Удалить все документы коллекции — пустой фильтр (будьте предельно внимательны, отката нет):
db.logs.deleteMany({})Если нужно убрать саму коллекцию вместе с индексами — это уже не удаление документов, а drop:
db.logs.drop()Чем удаление отличается от $unset
Не путайте уровни: deleteOne удаляет документ целиком, а $unset убирает поле внутри документа. Первое — про записи, второе — про их содержимое.
Итог
{ upsert: true }создаёт документ, если под фильтр ничего не подошло — «обнови или вставь» одним запросом.replaceOneзаменяет содержимое документа целиком (кроме_id), без операторов.deleteOne/deleteManyудаляют документы;{}— все;drop()сносит коллекцию.