Обновление записей MongoDB

MongoDBBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы научитесь обновлять документы в коллекции MongoDB. Сначала вы модифицируете один документ с помощью метода updateOne(). Затем вы научитесь одновременно модифицировать несколько документов с помощью метода updateMany(). Вы также будете работать с различными операторами обновления, такими как $set, $inc и $unset, для выполнения конкретных модификаций. Наконец, вы изучите опцию upsert, которая позволяет либо обновить существующий документ, либо создать новый, если он не существует. Эта лабораторная работа предоставляет практический, прикладной подход к освоению фундаментальных навыков манипулирования данными в MongoDB.

Обновление одного документа с помощью updateOne

На этом шаге вы научитесь модифицировать один документ в коллекции MongoDB. Мы будем использовать метод updateOne() вместе с оператором $set для изменения значения поля в конкретном документе.

Сначала откройте MongoDB Shell для взаимодействия с вашей базой данных.

mongosh

Находясь в оболочке, переключитесь на базу данных mylab_database, которая была подготовлена для вас.

use mylab_database

Давайте посмотрим текущие документы в коллекции books. Метод .pretty() форматирует вывод, делая его более читаемым.

db.books.find().pretty();

Вы должны увидеть три исходных документа книг. Значения _id будут уникальными в вашей среде.

[
  {
    _id: ObjectId("..."),
    title: 'JavaScript Fundamentals',
    author: 'Mike Johnson',
    year: 2022,
    pages: 350
  },
  {
    _id: ObjectId("..."),
    title: 'Python Deep Dive',
    author: 'Sarah Williams',
    year: 2021,
    pages: 450
  },
  {
    _id: ObjectId("..."),
    title: 'Machine Learning Basics',
    author: 'John Doe',
    year: 2020,
    price: 39.99
  }
]

Теперь давайте обновим год публикации книги "JavaScript Fundamentals" на 2023.

db.books.updateOne(
  { title: "JavaScript Fundamentals" },
  { $set: { year: 2023 } }
);

Разберем эту команду:

  • updateOne(): Этот метод находит первый документ, соответствующий фильтру, и обновляет его.
  • { title: "JavaScript Fundamentals" }: Это документ фильтра. Он указывает MongoDB найти документ, где поле title имеет значение "JavaScript Fundamentals".
  • { $set: { year: 2023 } }: Это документ обновления. Оператор $set заменяет значение поля year на 2023.

Команда возвращает объект результата, подтверждающий операцию.

{
  "acknowledged": true,
  "insertedId": null,
  "matchedCount": 1,
  "modifiedCount": 1,
  "upsertedCount": 0
}

matchedCount: 1 показывает, что один документ совпал с нашим фильтром, а modifiedCount: 1 показывает, что один документ был успешно обновлен.

Чтобы проверить изменение, найдите документ снова.

db.books.findOne({ title: "JavaScript Fundamentals" });

В выводе будет показан обновленный документ с новым годом.

{
  _id: ObjectId("..."),
  title: 'JavaScript Fundamentals',
  author: 'Mike Johnson',
  year: 2023,
  pages: 350
}

Обновление нескольких документов с помощью updateMany

Иногда вам нужно обновить несколько документов одновременно. Для этого MongoDB предоставляет метод updateMany(). На этом шаге вы добавите новое поле ко всем книгам, опубликованным до определенного года.

Давайте добавим поле status со значением "Classic" ко всем книгам, опубликованным до 2022 года.

db.books.updateMany({ year: { $lt: 2022 } }, { $set: { status: "Classic" } });

Вот объяснение команды:

  • updateMany(): Этот метод обновляет все документы, соответствующие указанному фильтру.
  • { year: { $lt: 2022 } }: Этот фильтр выбирает документы, где year меньше 2022. Оператор $lt означает "less than" (меньше чем).
  • { $set: { status: "Classic" } }: Этот документ обновления добавляет новое поле status со значением "Classic" ко всем соответствующим документам.

Вывод покажет, сколько документов было найдено и модифицировано. В нашем случае две книги были опубликованы до 2022 года.

{
  "acknowledged": true,
  "insertedId": null,
  "matchedCount": 2,
  "modifiedCount": 2,
  "upsertedCount": 0
}

Чтобы убедиться, что оба документа были обновлены, вы можете выполнить запрос для всех книг со статусом "Classic".

db.books.find({ status: "Classic" }).pretty();

Вы увидите две книги, которые теперь включают поле status.

[
  {
    _id: ObjectId("..."),
    title: 'Python Deep Dive',
    author: 'Sarah Williams',
    year: 2021,
    pages: 450,
    status: 'Classic'
  },
  {
    _id: ObjectId("..."),
    title: 'Machine Learning Basics',
    author: 'John Doe',
    year: 2020,
    price: 39.99,
    status: 'Classic'
  }
]

Использование дополнительных операторов обновления: $inc и $unset

MongoDB предлагает различные операторы для разных типов обновлений. На этом шаге вы научитесь использовать $inc для изменения числовых значений и $unset для удаления полей из документа.

Сначала давайте используем оператор $inc для увеличения количества страниц в книге "Python Deep Dive" на 50. Оператор $inc увеличивает значение поля на указанную величину.

db.books.updateOne({ title: "Python Deep Dive" }, { $inc: { pages: 50 } });

Чтобы подтвердить изменение, получите документ.

db.books.findOne({ title: "Python Deep Dive" });

Поле pages теперь должно быть 500 (450 + 50).

{
  _id: ObjectId("..."),
  title: 'Python Deep Dive',
  author: 'Sarah Williams',
  year: 2021,
  pages: 500,
  status: 'Classic'
}

Далее, давайте удалим поле price из документа "Machine Learning Basics". Оператор $unset удаляет указанное поле. Значение, передаваемое $unset (в данном случае ""), не имеет значения и может быть любым.

db.books.updateOne(
  { title: "Machine Learning Basics" },
  { $unset: { price: "" } }
);

Давайте проверим, что поле price было удалено.

db.books.findOne({ title: "Machine Learning Basics" });

В выводе будет показан документ без поля price.

{
  _id: ObjectId("..."),
  title: 'Machine Learning Basics',
  author: 'John Doe',
  year: 2020,
  status: 'Classic'
}

Создание документов с помощью upsert

"Upsert" (обновление или вставка) — это особый тип операции обновления, который либо обновляет документ, если он существует, либо вставляет новый, если его нет. Это полезно для того, чтобы избежать раздельной логики "проверить, затем вставить" и обеспечивает атомарность операций с базой данных. Операции Upsert особенно ценны в сценариях, когда вы хотите:

  • Обеспечить согласованность данных: Вместо того чтобы сначала проверять существование документа, а затем решать, вставлять или обновлять, вы можете выполнить одну атомарную операцию, которая обрабатывает оба случая.
  • Обрабатывать параллельные операции: В многопользовательской среде upsert предотвращает состояние гонки (race conditions), когда другой процесс может вставить тот же документ между вашей операцией проверки и вставки.
  • Упростить логику приложения: Уменьшает потребность в сложной условной логике в коде вашего приложения, делая его более поддерживаемым и менее подверженным ошибкам.

Вы можете включить это поведение, добавив опцию upsert: true к вашей команде обновления.

Попробуем добавить новую книгу, "Cloud Computing Essentials". Поскольку этой книги нет в нашей коллекции, операция upsert ее создаст.

db.books.updateOne(
  { title: "Cloud Computing Essentials" },
  { $set: { author: "David Lee", year: 2023, pages: 300 } },
  { upsert: true }
);

Команда состоит из трех частей:

  1. Фильтр: { title: "Cloud Computing Essentials" }
  2. Обновление: { $set: { ... } }
  3. Опции: { upsert: true }

Поскольку ни один документ не соответствовал фильтру, был создан новый. Объект результата отражает это, включая upsertedId.

{
  acknowledged: true,
  matchedCount: 0,
  modifiedCount: 0,
  upsertedCount: 1,
  upsertedId: ObjectId("...")
}

Теперь давайте выполним ту же команду еще раз. На этот раз MongoDB найдет только что созданный документ и обновит его.

db.books.updateOne(
  { title: "Cloud Computing Essentials" },
  { $set: { author: "David Lee", year: 2023, pages: 300 } },
  { upsert: true }
);

Результат теперь показывает matchedCount: 1. Поскольку данные, которые мы устанавливаем, совпадают с существующими данными, modifiedCount равен 0. Если бы мы изменили значение, modifiedCount был бы равен 1.

{
  "acknowledged": true,
  "insertedId": null,
  "matchedCount": 1,
  "modifiedCount": 0,
  "upsertedCount": 0
}

Вы можете убедиться, что новая книга существует в коллекции.

db.books.findOne({ title: "Cloud Computing Essentials" });

Вывод отобразит только что созданный документ.

{
  _id: ObjectId("..."),
  title: 'Cloud Computing Essentials',
  author: 'David Lee',
  year: 2023,
  pages: 300
}

Когда вы закончите, вы можете выйти из оболочки MongoDB Shell.

exit;

Резюме

В этой лабораторной работе вы изучили основные методы обновления документов в MongoDB. Вы практиковались в изменении отдельных документов с помощью updateOne и нескольких документов с помощью updateMany. Вы также познакомились с мощными операторами обновления, включая $set для изменения значений полей, $inc для инкремента числовых значений и $unset для удаления полей. Наконец, вы узнали, как использовать опцию upsert для создания документа, если он еще не существует. Эти навыки являются основополагающими для управления и поддержки данных в любом приложении MongoDB.