Опубликован: 12.03.2016 | Доступ: свободный | Студентов: 1006 / 221 | Длительность: 04:48:00
Лекция 3:

Обновление

< Лекция 2 || Лекция 3 || Лекция 4 >
Ключевые слова: CRUD, create, read, UPDATE, AND, DELETE

В первой главе мы изучили три из четырёх операций 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}.

< Лекция 2 || Лекция 3 || Лекция 4 >