Работа с массивами в документах
Как добавлять, удалять и обновлять элементы массива, не переписывая весь документ.
Массивы — родная часть документной модели: для их изменения есть отдельные операторы $push, $pull, $addToSet.
Зачем отдельные операторы
Пусть у пользователя есть массив тегов. Можно было бы прочитать документ, изменить массив в приложении и записать обратно — но это та же гонка, что и с числами. Операторы массивов меняют его прямо в базе, атомарно.
{
"_id": "u1",
"name": "Анна",
"tags": ["js", "css"]
}$push — добавить в конец
$push дописывает элемент в массив:
db.users.updateOne(
{ _id: "u1" },
{ $push: { tags: "mongodb" } }
)Добавить сразу несколько — через $each:
db.users.updateOne(
{ _id: "u1" },
{ $push: { tags: { $each: ["node", "react"] } } }
)$addToSet — без дубликатов
$push добавляет всегда, даже если такой элемент уже есть. Если массив должен хранить только уникальные значения (множество), используйте $addToSet — он добавит элемент, только если его там ещё нет:
db.users.updateOne(
{ _id: "u1" },
{ $addToSet: { tags: "js" } } // "js" уже есть — массив не изменится
)$pull — удалить по условию
$pull убирает из массива все элементы, подходящие под условие. Удалить тег css:
db.users.updateOne(
{ _id: "u1" },
{ $pull: { tags: "css" } }
)Условие может быть и сложнее. Если массив состоит из чисел, удалить все меньше 10:
db.users.updateOne(
{ _id: "u1" },
{ $pull: { scores: { $lt: 10 } } }
)Снять самый последний элемент поможет $pop (1 — с конца, -1 — с начала):
db.users.updateOne({ _id: "u1" }, { $pop: { tags: 1 } })Обновить элемент массива объектов
Часто массив состоит из объектов — например, позиции заказа. Чтобы изменить совпавший элемент, используют позиционный оператор $: он указывает на элемент, который подошёл под фильтр. Увеличим количество у товара SKU-1001 внутри заказа:
db.orders.updateOne(
{ _id: "o1", "items.sku": "SKU-1001" },
{ $set: { "items.$.qty": 3 } }
)Здесь items.$.qty читается как «у того элемента массива items, что совпал с фильтром, поле qty». Это ключевой приём для работы с вложенными массивами объектов.
Итог
$pushдобавляет элемент (с$each— несколько),$addToSet— только если его ещё нет.$pullудаляет элементы по условию,$pop— крайний элемент массива.- Позиционный оператор
$обновляет элемент массива, совпавший с фильтром запроса.