Перевод: Paras — Learn MongoDB: Update Documents
Рассмотрев запросы к документам, пришло время научиться редактировать документы. Если вы знаете, как найти свои данные, вам будет проще их изменять. Итак, приступим!
Содержание :
Методы, которые помогают нам изменять документы в mongodb:
В этом посте мы будем работать с коллекцией trainers
. Хватит покемонов !! Для начала сделаем простую структуру:
{ name: "Ash", age: 18, pokemons: [ { name: "pikachu", type: "electric", level: 16 }, { name: "charizard", type: "fire", level: 30 }, { name: "squirtle", type: "water", level: 12 } ], badges: ["boulder badge", "cascade badge"], exp: 200, currentTown: "Pallet Town" }
Далее мы будем добавлять данные и изменять структуру в соответствии с нашими потребностями.
Первый оператор, с которым вам следует познакомится для обновления документов, — это $set. Если мы попытаемся обновить документы без этого оператора, это приведет к ошибке или неожиданному поведению.
Методы обновления принимают первый параметр в качестве фильтра документов для определения документов, которые вы хотите обновить, и второй параметр значение, которое вы хотите применить к отфильтрованным документам. Есть третий параметр, но мы узнаем о нем позже в этом посте.
Базовый пример
# меняем имя тренера с Ash на Misty > db.trainers.updateOne( {name: "Ash"}, {$set: {name: "Misty"}} ) # задаем возраст всех тренеров 18 > db.trainers.updateMany({}, {$set: {age: 18}}) # задаем новое поле для всех тренеров > db.trainers.updateMany( {}, {$set: {hasPokemon: false}} )
Вы не знаете, но mongo достаточно умен, и если вы попытаетесь обновить поле с тем же значением, которое у него уже есть, оно проигнорирует эту команду
Операторы обновления помогают нам обновлять документы разными способами.
Операторы:
Для выполнения умножения числовых полей существуют и другие операторы, которые также помогают вам работать с массивами, и мы обсудим их позже.
Итак, давайте посмотрим несколько примеров для вышеуказанных операторов и их использования.
Структура документа Trainers
{ name: "Ash", age: 18, pokemons: [ { name: "pikachu", type: "electric", level: 16 }, { name: "charizard", type: "fire", level: 30 }, { name: "squirtle", type: "water", level: 12 } ], badges: ["boulder badge", "cascade badge"], exp: 200, currentTown: "Pallet Town", bagItems: { pokeballs: 8, heals: 10 }, isFunny: true }
Пример:
# увеличиваем опыт "Ash" на 50 > db.trainers.updateOne({name: "Ash"}, {$inc: {exp: 50}}) # уменьшаем количество pokeballs в мешке Ash на 2 > db.trainers.updateOne({name: "Ash"}, {$inc: {"bagItems.pokeballs": -2}})
# обновляем количество heals в сумке Ash, если в ней heals меньше значения обновления # это будет обновляться, только если переданное значение меньше значения в db > db.trainers.updateOne({name: "Ash"}, {$min: {"bagItems.heals": 25}}) # обновляем exp до 300, только если новый exp. больше текущего exp > db.trainers.updateOne({name: "Brock"}, {$max: {exp: 300}})
# умножаем exp Ash(и сделаем его непобедимым !!) > db.trainers.updateOne({name: "Ash"}, {$mul: {exp: 100}})
# удаляем поле "isFunny" со всех документов > db.trainers.updateMany({}, {$unset: {isFunny: ""}}) # ПРИМЕЧАНИЕ 1. Значение, которое вы передаете в поле, может быть любым. Здесь важно имя поля # ПРИМЕЧАНИЕ 2. Вы также можете удалить вложенные поля в документах, например. "bagItems.heals"
# переименовываем поле "exp" в "experience" > db.trainers.updateMany({}, {$rename: {exp: "experience"}})
> db.trainers.updateOne( {name: "Paul"}, {$set: {age: 19, exp: 200}}, {upsert: true} )
Здесь вы видите третий аргумент, который принимает метод updateOne. Это похоже на параметры запроса, которые вы можете изменять. По умолчанию для upsert установлено значение false. Сделав upsert истинным, мы получили метод обновления и метод создания как в нашем обновлении.
Результат вышеуказанного запроса
{ name: "Paul", age: 19, exp: 200 }
Как видите, mongo не только создает документ с новыми полями, но также добавляет поле, которое мы передали как фильтр в первом аргументе. Круто, не правда ли.
Обновление массивов немного отличается от обновления других полей в документе или вложенных документах. Но это не ракетостроение.
Начнем с некоторых операторов, которые могут помочь нам выполнять основные операции с массивами.
$push
; добавить элемент в массив в документе$pull
: удалить указанный элемент из массива в документе$pop
: удалить элемент из массива либо с конца, либо с начала$each
: помогает протолкнуть сразу несколько элементов вместо одного$addToSet
: обрабатывает массив как набор и добавляет значение, только если оно не существуетПример:
# добавляем нового покемона к покемонам Ash > db.trainers.updateOne( {name: "Ash"}, {$push: { pokemons: { name: "bulbasaur", type: "grass", level: 17 }}} ) # добавляем боле чем одного покемона к покемонам Ash с $each > db.trainers.updateOne( {name: "Ash"}, { $push: { pokemons: { $each: [ {name: "butterfree", type: "bug", level: 20}, {name: "piggeotto", type: "flying", level: 14}, {name: "Krabby", type: "water", level: 13} ]} } } ) # удаляем badge из массива Ash > db.trainers.updateOne( {name: "Ash"}, {$pull: {badges: "boulder badge"}} ) # давай еще заберем покемона у Ash(в шутку) > db.trainers.updateOne( {name: "Ash"}, {$pull: {pokemons: {name: "krabby"}}} ) # вытащить покемона из Misty с конца > db.trainers.updateOne({name: "Misty"}, {$pop: {pokemons: 1}}) # вытащить покемона из Misty с самого начала > db.trainers.updateOne({name: "Misty"}, {$pop: {pokemons: -1}}) # мы дадим Brock badge , но мы должны убедиться, что у него нет двух значков одного типа. Для этого нам нужно рассматривать массив как набор set > db.trainers.updateOne( {name: "Brock"}, {$addToSet: {badges: "Thunder Badge"}} ) # попробуйте сделать этот запрос еще раз, и вы заметите, что он не добавит еще один значок Thunder к значкам Brock.
Есть и другие операции, связанные с позициями в массиве. Может быть, вы хотите обновить четвертый элемент в массиве (по 3-му индексу) или хотите обновить все совпавшие элементы в массиве, а не только один. Таких ситуаций много.
Работа с индексом
# Повышает уровень первого покемона Ash на 1 > db.trainers.updateOne({name: "Ash"}, {$inc: {"pokemons.0.level": 1}})
Мы можем найти определенный элемент в массиве и обновить этот конкретный элемент, не зная его индекса.
$
: Вместо передачи индекса мы можем использовать этот позиционный оператор для ссылки на совпадающие результаты из нашего фильтра cм. пример ниже.
Запросить и обновить соответствующий элемент в массиве
# добавим поле health ко всем тренерам пикачу. > db.trainers.updateOne( {"pokemon.name": "pikachu"}, # соответствующий фильтр {$set: {"pokemons.$.health": 150}} # изменяемые параметры ) # Оператор '$' определяет, какой элемент документа запроса соответствует, а затем применяем к нему соответствующие значения
ПРИМЕЧАНИЕ: оператор $ обновляет только первый элемент, а не все элементы в массиве. Что это значит ? Это означает, что если у тренера более одного пикачу, будет обновлен только первый пикачу в его массиве покемонов.
Использование опции фильтр массива
Вышеупомянутая проблема с позиционным оператором, который обновляет только первое совпадение в массиве, может быть легко решена с помощью фильтров массива. Это поможет вам выбрать все документы, которые вы хотите обновить. Давайте создадим ситуацию для запроса и решим ее.
Предположим, мы хотим найти тренеров с experience 200 и выше и научить их покемонов типа grass движению «Solar beam». У тренера может быть несколько покемонов типа grass, поэтому мы должны обучать всех покемонов этого типа.
Запрос:
> db.trainers.updateMany( {experience: {$gte: 200}}, {$set: {"pokemons.$[poke].move": "Solar beam"}}, {applyFilters: [{"poke.type": "grass"}]} )
Объяснение:
// это не сработает [{"poke.type": "grass"}, {"poke.level": {$gte: 14}}] // вместо этого используйте $and, $or или другие операторы [{ $and: [ {"poke.type": "grass"}, {"poke.level": {$gte: 14}} ] }]
Обратитесь к документации для получения более подробной информации.
Обратите внимание, что в документации используется метод update, а не updateOne или updateMany. Поэтому, когда они хотят использовать updateMany, они передают {multi: true} в параметрах.
На этом все! Если есть вопросы, задавайте их в комментариях (в блоге автора статьи). Я постараюсь ответить на них.
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…
View Comments
Хорошая и понятная статья, но в этом решении мне помог не applyFilters, а arrayFilters