Операторы обновления полей
Набор модификаторов, который меняет поля, не вытягивая документ в приложение.
Операторы обновления позволяют менять отдельные поля атомарно прямо в базе — без чтения документа и обратной записи.
$set и $unset
С $set вы уже знакомы — он задаёт значение поля (создаёт, если поля не было). Противоположность — $unset, который удаляет поле из документа целиком:
db.users.updateOne(
{ name: "Анна" },
{ $unset: { phone: "" } }
)Значение справа от $unset не важно (принято писать "") — поле просто исчезнет. Это не то же, что выставить null: при $unset поля не будет вообще, и $exists: false станет для него истинным.
$inc — увеличить или уменьшить число
Менять числовое поле через чтение-и-запись опасно: между ними кто-то может изменить значение. $inc делает это атомарно. Уменьшим остаток на складе на 1 при продаже:
db.products.updateOne(
{ _id: "SKU-1001" },
{ $inc: { stock: -1 } }
)Положительное число увеличивает, отрицательное уменьшает. Удобно для счётчиков просмотров, лайков, остатков:
db.articles.updateOne(
{ _id: "a1" },
{ $inc: { views: 1 } }
)$mul, $min, $max
Похожие числовые операторы: $mul умножает поле, $min/$max записывают значение только если оно меньше/больше текущего. Поднять цену на 10%:
db.products.updateMany(
{},
{ $mul: { price: 1.1 } }
)Зафиксировать рекордный максимум, не перезаписывая большее значение меньшим:
db.players.updateOne(
{ _id: "p1" },
{ $max: { highScore: 980 } }
)$rename — переименовать поле
Когда нужно сменить имя поля во всех документах (например, привести базу к новому соглашению), пригодится $rename:
db.users.updateMany(
{},
{ $rename: { "fio": "fullName" } }
)Почему это лучше, чем читать и переписывать
Можно было бы прочитать документ в приложение, поменять число и записать обратно. Но это две операции с «окном» между ними: параллельный запрос успеет вмешаться, и счётчик собьётся. Операторы вроде $inc выполняются на сервере атомарно — для одного документа MongoDB гарантирует, что обновление не перемешается с другими. Это и быстрее, и безопаснее.
Итог
$setзадаёт поле,$unsetудаляет его (не путать с установкойnull).$incатомарно меняет число — идеален для счётчиков и остатков; есть также$mul,$min,$max.- Операторы работают на сервере атомарно для одного документа — безопаснее, чем «прочитал-изменил-записал».