В прошлом уроке мы собирали витрину: находили книги, сортировали и резали на страницы. Но магазин живёт: цены меняются, книги заканчиваются, у отзывов появляются ответы. Сегодня учимся менять документы, которые уже лежат в базе. Примеры на учебной базе магазина.
Исправление в карточке
В библиотечном каталоге у каждой книги своя карточка. Когда книгу переносят на другую полку, библиотекарь не переписывает карточку целиком. Он находит нужную, зачёркивает старый номер полки и пишет новый, а название и автор остаются как были.
Обновление в MongoDB устроено так же, и у него две части:
- Фильтр: какие документы менять. Это тот же образец, что мы передавали в
find. - Документ обновления: что в них поменять. Он состоит из операторов, самый частый из которых
$set, «поставь полю такое значение».
Если сравнивать с SQL, фильтр это WHERE, а $set это SET из урока про UPDATE в PostgreSQL.
updateOne: один документ
«Собачье сердце» подорожало до 420 рублей:
db.books.updateOne({ _id: 2 }, { $set: { price: 420 } })
db.books.findOne({ _id: 2 }, { title: 1, price: 1 })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
{ _id: 2, title: 'Собачье сердце', price: 420 }
Сервер отвечает не самим документом, а отчётом о работе. Нам важны два числа:
matchedCount: сколько документов подошло под фильтр;modifiedCount: сколько из них действительно изменилось.
Остальные поля пригодятся в уроке про upsert, где обновление умеет превращаться во вставку.
Числа расходятся чаще, чем кажется. Выполним ту же команду ещё раз:
db.books.updateOne({ _id: 2 }, { $set: { price: 420 } })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 0,
upsertedCount: 0
}
Документ нашёлся, но цена уже 420, менять нечего. MongoDB не перезаписывает поле тем же значением и честно пишет modifiedCount: 0.
А если фильтр не подошёл ни к одному документу, ошибки не будет. Будут два нуля:
db.books.updateOne({ _id: 42 }, { $set: { price: 100 } })
{
acknowledged: true,
insertedId: null,
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 0
}
Поэтому после обновления в коде приложения смотрят на matchedCount. Ноль там значит «такой книги нет», и это стоит показать пользователю, а не молча считать, что всё получилось.
урок из курса
Урок из курса «MongoDB с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.