Введение
В этой лабораторной работе вы научитесь эффективно управлять вложенными документами в MongoDB. Вложенные документы (embedded documents, nested documents) являются основной особенностью модели данных MongoDB, позволяющей хранить сложные иерархические данные в одном документе. Вы освоите ряд техник, включая создание документов с вложенными данными, обновление конкретных полей внутри них, удаление элементов и выполнение запросов к этим сложным структурам. Вы также узнаете, как обеспечивать согласованность структуры данных с помощью валидации схемы (schema validation). Эти навыки необходимы для создания надежных и эффективных приложений с использованием MongoDB.
Создание документов с вложенными данными
На этом шаге вы научитесь создавать документы со вложенными структурами в MongoDB. Это фундаментальный навык для моделирования связанных данных в одном документе.
Сначала откройте MongoDB Shell (mongosh), чтобы начать взаимодействие с базой данных. Все последующие команды в этой лабораторной работе будут выполняться в этой оболочке, если не указано иное.
mongosh
Далее переключитесь на новую базу данных с именем bookstore. Если эта база данных не существует, MongoDB создаст ее для вас при первом сохранении данных.
use bookstore
Теперь вы создадите коллекцию с именем books и вставите один документ. Этот документ будет содержать вложенные объекты и массив вложенных объектов, представляющих детали книги.
db.books.insertOne({
title: "Advanced MongoDB",
author: {
name: "Jane Smith",
contact: {
email: "jane.smith@example.com",
phone: "+1-555-123-4567"
}
},
published: {
year: 2023,
publisher: "Tech Publications"
},
chapters: [
{ number: 1, title: "Introduction to Nested Documents" },
{ number: 2, title: "Advanced Document Structures" }
]
})
В документе, который вы только что создали:
authorиpublishedявляются вложенными документами (объектами).- Документ
authorсодержит еще один вложенный документ,contact. chapters— это массив, содержащий несколько вложенных документов, каждый из которых представляет главу.
Чтобы просмотреть документ и подтвердить его структуру, используйте метод find().
db.books.find()
Вы должны увидеть следующий вывод, подтверждающий, что документ был вставлен правильно. _id — это уникальный идентификатор, автоматически генерируемый MongoDB.
[
{
_id: ObjectId("..."),
title: 'Advanced MongoDB',
author: {
name: 'Jane Smith',
contact: {
email: 'jane.smith@example.com',
phone: '+1-555-123-4567'
}
},
published: {
year: 2023,
publisher: 'Tech Publications'
},
chapters: [
{ number: 1, title: 'Introduction to Nested Documents' },
{ number: 2, title: 'Advanced Document Structures' }
]
}
]
Обновление вложенных полей и элементов массива
После создания документов вам часто потребуется изменять их части. На этом шаге вы научитесь обновлять конкретные поля во вложенных документах и массивах. Вы все еще должны находиться в оболочке mongosh из предыдущего шага.
Сначала давайте обновим контактную информацию автора. Для этого вы используете оператор $set с точечной нотацией (dot notation), чтобы указать точный путь к полю, которое вы хотите изменить. Эта команда изменит номер телефона и добавит новое поле website.
db.books.updateOne(
{ title: "Advanced MongoDB" },
{ $set: {
"author.contact.phone": "+1-888-999-0000",
"author.contact.website": "www.janesmith.com"
} }
)
Точечная нотация "author.contact.phone" указывает MongoDB перейти в объект author, затем в объект contact и обновить поле phone.
Далее вы добавите новую главу в массив chapters, используя оператор $push.
db.books.updateOne(
{ title: "Advanced MongoDB" },
{ $push: {
chapters: {
number: 3,
title: "MongoDB Advanced Techniques"
}
} }
)
Вы также можете обновить конкретный элемент внутри массива. Давайте изменим название первой главы. Мы используем позиционный оператор $ , который действует как заполнитель для первого элемента массива, соответствующего условию запроса ("chapters.number": 1).
db.books.updateOne(
{ title: "Advanced MongoDB", "chapters.number": 1 },
{ $set: {
"chapters.$.title": "Introduction to Nested Documents (Revised)"
} }
)
Чтобы проверить все изменения, получите документ снова. Метод .pretty() форматирует вывод для лучшей читаемости.
db.books.find({ title: "Advanced MongoDB" }).pretty()
В выводе будет показан обновленный номер телефона, новый веб-сайт, добавленная третья глава и измененное название первой главы.
Удаление вложенных полей и элементов массива
На этом шаге вы научитесь удалять части ваших документов. Это включает удаление конкретных полей, целых вложенных документов и элементов из массива.
Сначала давайте удалим поле website из контактной информации автора, используя оператор $unset. Значение, передаваемое $unset (в данном случае пустая строка ""), не имеет значения; оператор просто удаляет указанное поле.
db.books.updateOne(
{ title: "Advanced MongoDB" },
{ $unset: { "author.contact.website": "" } }
)
Далее вы удалите элемент из массива. Давайте удалим третью главу (ту, у которой number: 3) из массива chapters, используя оператор $pull. Оператор $pull удаляет все элементы массива, соответствующие указанному условию.
db.books.updateOne(
{ title: "Advanced MongoDB" },
{ $pull: {
chapters: { number: 3 }
} }
)
Наконец, вы можете удалить весь вложенный объект. Давайте удалим объект contact из документа author, снова используя оператор $unset.
db.books.updateOne(
{ title: "Advanced MongoDB" },
{ $unset: { "author.contact": "" } }
)
Чтобы увидеть результат этих операций удаления, снова выполните запрос к документу.
db.books.find({ title: "Advanced MongoDB" }).pretty()
В выводе будет показано, что поле website и весь объект contact отсутствуют, а массив chapters теперь содержит только два элемента.
Запрос документов с вложенными данными
Запрос данных является фундаментальной операцией базы данных. На этом шаге вы научитесь запрашивать документы на основе значений во вложенных объектах и массивах. Чтобы обеспечить наличие чистого набора данных для этих примеров, сначала удалите существующую коллекцию books.
db.books.drop()
Теперь вставьте несколько новых документов с различными вложенными структурами для практики запросов.
db.books.insertMany([
{
title: "MongoDB Essentials",
author: {
name: "John Doe",
experience: { years: 5, specialization: "Database Design" }
},
tags: ["beginner", "database", "nosql"],
chapters: [
{ number: 1, title: "Introduction", pages: 25 },
{ number: 2, title: "Advanced Concepts", pages: 45 }
]
},
{
title: "Advanced Database Techniques",
author: {
name: "Jane Smith",
experience: { years: 8, specialization: "Distributed Systems" }
},
tags: ["advanced", "distributed", "nosql"],
chapters: [
{ number: 1, title: "System Design", pages: 35 },
{ number: 2, title: "Performance Optimization", pages: 55 }
]
}
])
Чтобы найти книгу по полю во вложенном документе, используйте точечную нотацию (dot notation). Этот запрос находит книгу, написанную "John Doe".
db.books.find({ "author.name": "John Doe" })
Вы можете углубляться во вложенные структуры. Этот запрос находит книги, в которых специализация автора — "Database Design".
db.books.find({ "author.experience.specialization": "Database Design" })
Чтобы найти документы, где массив содержит определенное значение, вы можете напрямую запрашивать поле массива. Этот запрос находит все книги с тегом "nosql".
db.books.find({ tags: "nosql" })
Вы также можете запрашивать документы, где элемент массива соответствует определенному условию. Этот запрос находит книги, у которых есть хотя бы одна глава объемом более 40 страниц, используя оператор $gt (больше чем).
db.books.find({ "chapters.pages": { $gt: 40 } })
Наконец, вы можете комбинировать несколько условий. Этот запрос находит книги с тегом "advanced", написанные автором с опытом работы 5 лет и более ($gte означает больше или равно).
db.books.find({
"author.experience.years": { $gte: 5 },
tags: "advanced"
})
Применение структуры документов с валидацией схемы
Для поддержания согласованности данных MongoDB позволяет обеспечивать определенную структуру документов в коллекции с помощью валидации JSON Schema. На этом шаге вы создадите новую коллекцию с валидатором, чтобы гарантировать соответствие всех документов предопределенной структуре.
Сначала создайте новую коллекцию с именем courses. При ее создании вы передадите опцию validator, содержащую правила схемы.
db.createCollection("courses", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["title", "instructor", "duration", "topics"],
properties: {
title: {
bsonType: "string",
description: "must be a string and is required"
},
instructor: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string" },
email: {
bsonType: "string",
pattern: "^.+@.+$"
}
}
},
duration: {
bsonType: "int",
minimum: 1,
maximum: 100
},
topics: {
bsonType: "array",
minItems: 1,
items: { bsonType: "string" }
}
}
}
}
})
Эта схема требует, чтобы каждый документ имел поля title, instructor, duration и topics. Она также определяет тип данных для каждого поля, включая вложенные правила для объекта instructor и массива topics.
Теперь попробуйте вставить документ, соответствующий этим правилам. Эта операция должна пройти успешно.
db.courses.insertOne({
title: "MongoDB Advanced Techniques",
instructor: {
name: "Jane Smith",
email: "jane.smith@example.com"
},
duration: 40,
topics: ["Nested Documents", "Schema Validation"]
})
Далее попытайтесь вставить документ, нарушающий правила схемы. Этот документ имеет неправильный тип данных для instructor.name, недопустимый формат электронной почты, значение duration вне допустимого диапазона и пустой массив topics.
db.courses.insertOne({
title: "Invalid Course",
instructor: {
name: 123,
email: "invalid-email"
},
duration: 200,
topics: []
})
Эта вставка завершится ошибкой, и MongoDB вернет ошибку Document failed validation (Документ не прошел валидацию). Это предотвращает сохранение несогласованных данных и помогает поддерживать целостность вашей базы данных.
Резюме
В этой лабораторной работе вы изучили основные методы управления вложенными документами в MongoDB. Вы начали с создания документов со сложными вложенными структурами, включая объекты и массивы. Затем вы практиковались в обновлении конкретных полей с использованием точечной нотации (dot notation) и операторов, таких как $set и $push. Вы также узнали, как удалять данные с помощью $unset и $pull. Кроме того, вы исследовали, как выполнять целевые запросы к вложенным данным, и, наконец, как обеспечивать целостность данных путем определения и применения валидатора JSON Schema к коллекции. Эти навыки имеют решающее значение для создания приложений, которые эффективно используют гибкую модель документов MongoDB.

