Россия |
Обновление
В первой главе мы изучили три из четырёх операций CRUD (create, read, update and delete). Эта глава посвящена четвёртой: update. У update имеются некоторые особенности, вот почему мы посвящаем этому целую главу.
Обновление данных: замена и $set
В простейшей форме, update принимает 2 аргумента: селектор (where) для выборки и то, чем обновить соответствующее поле. Чтобы Roooooodles прибавил в весе, используем следующий запрос:
db.unicorns.update({name: 'Roooooodles'}, {weight: 590})
(Если в ходе экспериментов вы удалили данные из ранее созданной коллекции unicorns, сделайте всем документам remove, и вставьте их заново с помощью кода из главы 1)
В реальной жизни, конечно, следует обновлять документы, выбирая их по _id, однако, поскольку я не знаю какой _id MongoDB сгенерировала для вас, будем выбирать по имени - name. Теперь, давайте взглянем на обновленную запись:
db.unicorns.find({name: 'Roooooodles'})
Вот и первый сюрприз, который нам преподнёс update. Документ не найден, поскольку второй параметр используется для полной замены оригинала. Иными словами, update нашел документ по имени и заменил его целиком на новый документ (свой второй параметр). Вот в чём отличие от SQL-команды UPDATE. Иногда это идеальный вариант, который может использоваться для некоторых действительно динамических обновлений. Однако, если вам нужно всего лишь изменить пару полей, лучше всего использовать модификатор $set:
db.unicorns.update({weight: 590}, {$set: {name: 'Roooooodles', dob: new Date(1979, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}})
Это восстановит утерянные ранее поля. Поле weight не перезапишется, поскольку мы его не передали в запрос. Теперь, если выполнить:
db.unicorns.find({name: 'Roooooodles'})
мы получим ожидаемый результат. Таким образом, в первом примере правильно было бы обновить weight следующим образом:
db.unicorns.update({name: 'Roooooodles'}, {$set: {weight: 590}})
Модификаторы обновления
Кроме $set можно использовать и другие модификаторы для разных изящных вещей. Все эти модификаторы обновления действуют над полями - так что ваш документ не окажется перезаписан целиком. Например, модификатор $inc служит для того, чтобы изменить поле на положительную (увеличить) или отрицательную (уменьшить) величину . Например, если единорог Pilot был ошибочно награжден за убийство пары лишних вампиров, мы можем исправить эту ошибку следующим образом:
db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})
Если Aurora внезапно пристрастилась к сладостям, мы можем добавить соответствующее значение к ее полю loves с помощью модификатора $push:
db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}})
Информацию об остальных модификаторах можно найти в разделе Обновление на сайте MongoDB.
Обновление/вставка
Один из приятных сюрпризов операции обновления - это возможность обновления/вставки (upsert от update - обновить и insert - вставить) Обновление/вставка обновляет документ, если он найден, или создаёт новый - если не найден. Обновление/вставка - полезная вещь в некоторых случаях; когда столкнётесь с подобным, сразу поймёте. Чтобы разрешить вставку при обновлении, установите третий параметр в true.
Пример из жизни - счетчик посещений для веб-сайта. Если мы хотим в реальном времени видеть количество посещений страницы, мы должны посмотреть, существует ли запись, и - в зависимости от результата - выполнить update либо insert. Если опустить (или установить в false) третий параметр, следующий пример не сработает:
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}); db.hits.find();
Однако, если разрешить вставку при обновлении, результаты будут иными:
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true); db.hits.find();
Поскольку документы с полем page, равным unicorns, не существуют, то будет создан новый документ. Если выполнить это вторично, существующий документ будет обновлён, и поле hits увеличится до 2.
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true); db.hits.find();
Множественные обновления
Последний сюрприз метода update - это, то что он по умолчанию обновляет лишь один документ. До сих пор это было логично в случае с уже рассмотренными примерами. Однако, если выполнить что-нибудь вроде:
db.unicorns.update({}, {$set: {vaccinated: true }}); db.unicorns.find({vaccinated: true});
то вы очевидно будете ожидать, что все единороги будут привиты (vaccinated). Чтобы это сработало, нужно установить четвертый параметр в true:
db.unicorns.update({}, {$set: {vaccinated: true }}, false, true); db.unicorns.find({vaccinated: true});
В этой главе
Эта глава завершила введение в основные CRUD операции над коллекциями. Мы детально рассмотрели update и увидели три его интересных режима работы. Во-первых, в отличие от SQL-команды UPDATE, в MongoDB update заменяет документ целиком. Из-за этого модификатор $set очень полезен. Во-вторых, update поддерживает интуитивно простое обновление/вставку, которое особенно полезно с модификатором $inc. И, наконец, в-третьих, по умолчанию, update обновляет лишь первый найденный документ.
Помните, что мы рассматриваем MongoDB с точки зрения её консоли. Используемые вами драйверы и библиотеки могут иметь иное поведение и реализовывать иной API. Например, драйвер для Ruby сливает два параметра в один хэш: {:upsert => false, :multi => false}.