CRUD в MongoDB: пошаговое руководство

MongoDB — документная NoSQL‑БД, подходящая для гибкой модели данных. В статье объяснено, как загрузить сервер, подключиться к нему, выполнять базовые CRUD‑операции (insertOne/insertMany, find/findOne, updateOne/updateMany, deleteOne/deleteMany) на примере Node.js‑драйвера, а также приведены практические советы по моделированию схем, безопасности, тестам и плану развертывания.
Введение
MongoDB предоставляет возможность быстро создавать современные, легко доступные и изменяемые базы данных. Это документная NoSQL‑система, где данные хранятся в JSON‑подобных документах (BSON). Такой подход освобождает от жёстких табличных схем и позволяет быстрее итеративно развивать приложение.
Ключевые термины в одну строку
- NoSQL: семейство баз данных, не ориентированных на реляционные таблицы.
- CRUD: четыре операции — Create, Read, Update, Delete.
- Документ: единица хранения в MongoDB, похожая на JSON.
Почему читать дальше
Эта инструкция подходит начинающим и тем, кто знает SQL, но впервые работает с MongoDB. Помимо примеров кода, вы найдёте советы по безопасности, тестированию, миграции и роли‑ориентированные чек‑листы для разработчика, DBA и инженера по DevOps.
Что такое NoSQL и где MongoDB вписывается
NoSQL обычно понимают как «не только SQL» — семейство баз данных, отличающихся гибкой схемой или специализированной структурой (ключ‑значение, столбцовые, графовые, документные). MongoDB — документная БД: данные хранятся в документах, что удобно для вложенных структур и динамических схем.
Когда NoSQL полезен
- Быстрая эволюция модели данных при агильной разработке.
- Хранение вложенных объектов (например, массивы адресов или заказов внутри профиля пользователя).
- Высокая скорость записи и горизонтальная масштабируемость.
Когда стоит рассмотреть реляционные базы
- Сложные транзакции с множеством зависимостей между таблицами.
- Жёсткие ACID‑требования для всех операций (хотя MongoDB поддерживает транзакции с версии 4.x, у реляционных СУБД зрелая модель).
Что такое MongoDB (коротко)
MongoDB — открытая документная база данных. Документы хранятся в коллекциях и представляют собой пары ключ‑значение с поддержкой вложенных структур и массивов. MongoDB поддерживает основные CRUD‑операции, индексы, агрегирование и транзакции.
Факты по умолчанию
- Формат хранения: BSON (бинарный формат JSON).
- Порт по умолчанию: 27017.
- Локальная адресация: 127.0.0.1 (localhost).
Загрузка и установка MongoDB
Важно: вы можете использовать локальную установку или облачный сервис (MongoDB Atlas). Ниже — общий путь для локальной установки и запуска сервера.
- Скачайте дистрибутив с официального сайта MongoDB.
- Распакуйте/установите в удобную директорию.
- Создайте директорию для хранения данных (например, “mongodb-data”).
Выполнение сервера MongoDB локально
Запуск сервера производится командой, указывающей путь к исполняемому файлу mongod и каталог данных. Пример (вставлен как в исходном материале, с относительными путями):
/Users/Administrator/mongodb/bin/mongod.exe --dbpath=/Users/Administrator/mongodb-dataПояснения
- Первый путь указывает на исполняемый файл mongod.exe.
- Параметр –dbpath указывает каталог, где MongoDB сохраняет данные.
- На Windows или Linux пути будут другими; важно указать корректные абсолютные или относительные пути.
После запуска вы увидите вывод в консоли, среди которого важны две строки: адрес и порт. Пример:
{"t":{"$date":"2021-04-14T18:10:11.779-05:00"},"s":"I", "c":"NETWORK", "id":23015, "ctx":"listener","msg":"Listening on","attr":{"address":"127.0.0.1"}}
{"t":{"$date":"2021-04-14T18:10:11.797-05:00"},"s":"I", "c":"NETWORK", "id":23016, "ctx":"listener","msg":"Waiting for connections","attr":{"port":27017,"ssl":"off"}}Эти строки показывают localhost и порт по умолчанию (27017). Они понадобятся при подключении клиента.
Подключение клиентских драйверов
MongoDB поддерживает драйверы для большинства языков: Node.js, Python, Java, Go и т.д. В этой статье приведены примеры для Node.js‑драйвера (популярный вариант для web‑приложений).
Установка драйвера для Node.js:
npm install mongodbГлавная функция — MongoClient, которую мы используем для подключения.
Создание базы и коллекции: общая логика
В MongoDB нет необходимости заранее создавать базу данных и коллекции: при первой вставке документов они создаются автоматически. Тем не менее рекомендуется явно управлять правами доступа и индексами.
Выполнение CRUD‑операций на примерах (Node.js)
Перед примерами: не забудьте запускать MongoDB локально или иметь URL облачного кластера. В примерах используется URL подключения:
const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'user-manager';Вставка: insertOne и insertMany
Когда использовать
- insertOne — для единственной записи.
- insertMany — для групповой вставки (эффективнее, чем последовательные insertOne).
Пример insertOne:
// импорт драйвера и получение MongoClient
const { MongoClient } = require("mongodb");
const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'user-manager';
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) => {
if (error) {
return console.log('Не удалось подключиться к базе данных');
}
const db = client.db(databaseName);
db.collection('users').insertOne({ name: 'John Doe', age: '28' }, (error, result) => {
if (error) {
return console.log('Не удалось создать пользователя');
}
console.log(result.ops);
client.close();
});
});Пример insertMany:
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) => {
if (error) return console.log('Не удалось подключиться');
const db = client.db(databaseName);
db.collection('users').insertMany([
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 }
], (err, res) => {
if (err) return console.log('insertMany ошибка');
console.log(res.insertedCount);
client.close();
});
});Примечание: MongoDB автоматически генерирует поле _id, если вы его не задаёте.
Чтение: find и findOne
- findOne ищет один документ и возвращает объект или null.
- find возвращает курсор; чтобы получить массив, используйте .toArray(), а для потоковой обработки — итерации по курсору.
Пример findOne:
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) => {
if (error) return console.log('Не удалось подключиться');
const db = client.db(databaseName);
db.collection('users').findOne({ name: 'John Doe' }, (error, user) => {
if (error) return console.log('Не удалось найти пользователя');
console.log(user);
client.close();
});
});Пример find (несколько документов):
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, async (error, client) => {
if (error) return console.log('Не удалось подключиться');
const db = client.db(databaseName);
const cursor = db.collection('users').find({ age: { $gt: 20 } });
const users = await cursor.toArray();
console.log(users);
client.close();
});Обновление: updateOne и updateMany
Операторы обновления начинаются с $. Чаще всего используется $set, чтобы задать новые значения полей.
Пример updateOne:
// обновить возраст пользователя
db.collection('users').updateOne({ name: 'John Doe' }, { $set: { age: '29' } });Пример updateMany:
// добавить поле "active: true" всем пользователям старше 18
db.collection('users').updateMany({ age: { $gt: 18 } }, { $set: { active: true } });Важно: по умолчанию updateOne и updateMany не возвращают обновлённый документ. Чтобы получить документ, можно использовать findOneAndUpdate с опцией returnOriginal: false (или returnDocument: ‘after’ в новых драйверах).
Удаление: deleteOne и deleteMany
Пример deleteOne:
// удалить пользователя по имени
db.collection('users').deleteOne({ name: 'John Doe' });Пример deleteMany:
// удалить всех пользователей с возрастом 0
db.collection('users').deleteMany({ age: '0' });Удаление простое, но будьте осторожны с критериями: ошибочный фильтр может удалить больше записей, чем планировали.
Моделирование данных и практические рекомендации
- Проектируйте модель данных под запросы. Обычно легче нормализовать (ссылки) или денормализовать (вложенные документы) в зависимости от того, как вы читаете данные.
- Избегайте больших документов (>16 МБ). MongoDB ограничивает размер документа.
- Используйте индексирование для полей, по которым часто фильтруете или сортируете.
- Для полей с уникальными значениями используйте уникальные индексы.
- Планируйте шардирование при больших объёмах и высоких нагрузках.
Ментальные модели
- Документ = объект в коде. Подумайте: «я бы хотел получить этот объект целиком — тогда он должен быть документом».
- Коллекция = таблица, но без обязательной схемы.
- Индекс = оглавление книги; создавайте по часто используемым путям поиска.
Когда не использовать MongoDB (контрпримеры)
- Если ваш рабочий процесс требует множества сложных связей и сложных JOIN между большими таблицами, реляционные СУБД иногда удобнее.
- Если каждую операцию нужно выполнять в строгой ACID‑транзакции, и вы не хотите думать о распределённых ограничениях, реляционная СУБД может быть лучше.
Альтернативы
- PostgreSQL — мощная реляционная СУБД с поддержкой JSONB.
- Redis — быстрое key‑value хранилище для кэширования и простых структур.
- Cassandra — для очень больших распределённых нагрузок и линейной записи.
Производительность и индексы
- Индексы ускоряют чтение, но замедляют запись и занимают место.
- Используйте композитные индексы для часто встречающихся комбинаций полей.
- Профилируйте запросы с помощью explain() для поиска узких мест.
Пример использования explain():
db.collection('users').find({ age: { $gt: 20 } }).explain('executionStats')Транзакции и атомарность
С версии 4.0 MongoDB поддерживает транзакции на уровне нескольких документов в рамках replica set, а с версии 4.2 — в sharded кластере. Тем не менее операции в одном документе атомарны по‑умолчанию.
Совет: если можно спроектировать модель так, чтобы избегать распределённых транзакций, это упростит масштабирование.
Безопасность и харднинг
- Включите аутентификацию и используйте авторизацию по ролям.
- Не оставляйте сервер MongoDB доступным по публичному IP без VPN или TLS.
- Включите шифрование TLS для сетевого трафика и, при необходимости, шифрование на уровне диска.
- Регулярно обновляйте MongoDB и драйверы до поддерживаемых версий.
Пример создания пользователя с ролью:
db.createUser({ user: 'appUser', pwd: 'strongPassword', roles: [{ role: 'readWrite', db: 'user-manager' }] })Резервное копирование и восстановление
- Для небольших развёртываний можно использовать mongodump и mongorestore.
- В кластерных установках используйте снапшоты или решения резервного копирования от поставщика (например, MongoDB Ops Manager или Atlas Backups).
Пример mongodump:
mongodump --uri="mongodb://127.0.0.1:27017/user-manager" --out=/backups/user-manager-2025-01-01Миграция и совместимость версий
- Проверяйте совместимость driver<->server: обновляйте драйверы после тестирования.
- Миграция с реляционной СУБД требует проработки модели: нормализация → денормализация или ссылки.
Совет: создайте тестовый кластер, чтобы прогнать миграцию и убедиться в корректности запросов и индексов.
Роль‑ориентированные чек‑листы
Разработчик
- Понять модель документа для своей области.
- Написать тесты для CRUD (unit + интеграционные).
- Добавить необходимые индексы и покрывающие индексы для медленных запросов.
DBA
- Настроить резервное копирование и мониторинг.
- Планировать шардирование и репликацию.
- Проводить аудит прав доступа и журналов.
DevOps
- Автоматизировать развёртывание с учётом конфигураций для безопасности (TLS, firewall).
- Настроить мониторинг SLI/SLO (производительность, латентность запросов).
SOP: быстрая проверка перед релизом (playbook)
- Проверить, что все критические индексы в продакшн‑клателе есть.
- Проверить резервное копирование и восстановление на тестовом наборе.
- Проверить профилирование медленных запросов и оптимизировать.
- Проверить права пользователей и отключить анонимный доступ.
- Прогнать прогонную нагрузочную тест‑сессию.
Критерии приёмки
- Все CRUD‑функции проходят интеграционные тесты.
- Время ответа для типичных запросов укладывается в заданные SLO.
- Нет непреднамеренных удалений данных при тестовых сценариях.
- Резервное копирование восстановило базу в тестовом окружении.
Тестовые случаи и приёмка
- TC1: insertOne создаёт документ и возвращает _id.
- TC2: findOne по уникальному полю возвращает ожидаемый объект.
- TC3: updateOne изменяет поле и не создаёт дубликатов.
- TC4: deleteOne удаляет только один документ с указанным фильтром.
Шаблон: чек‑лист для проверки производительности
- Проверить explain() для медленных запросов.
- Оценить процент полносканирования коллекции (COLLSCAN).
- Проверить использование индексов при фильтрах и сортировках.
Краткий чек‑лист миграции с реляционной БД
- Проанализировать частые запросы и выбрать модель: вложенные документы или ссылки.
- Перенести сущности с учётом ограничений размера документа.
- Построить индексы, эквивалентные ведущим операциям SELECT.
- Прогнать тестовые запросы и сравнить результаты и производительность.
Примеры типичных ошибок и как их избегать
- Ошибка: создание индекса в продакшне блокирует ресурсы.
Решение: создавайте индексы в off‑peak время или используйте фоновую сборку индексов. - Ошибка: хранение больших бинарных данных в документах.
Решение: используйте GridFS или внешнее хранилище для больших файлов.
FAQ
В: Поддерживает ли MongoDB транзакции?
Да. MongoDB поддерживает многодокументные транзакции в replica set и sharded кластере в современных версиях. Однако транзакции влияют на производительность, поэтому по возможности проектируйте модель так, чтобы их минимизировать.
В: Какой размер документа в MongoDB допустим?
Ограничение размера документа — 16 МБ. Для больших данных используйте GridFS.
В: Нужен ли мне жёсткий контроль схемы?
Нет, MongoDB позволяет гибкую схему, но рекомендуется использовать валидацию схемы (schema validation) или сторонние проверки на уровне приложения для контроля качества данных.
Image Credit: Alexander Sosluev/ WiKiMedia Commons
Короткое резюме
- MongoDB подходит для гибкой и быстрой разработки с документной моделью данных.
- CRUD‑операции просты: insertOne/insertMany, find/findOne, updateOne/updateMany, deleteOne/deleteMany.
- Обратите внимание на индексы, безопасность, резервное копирование и тестирование перед релизом.
Важно
Перед переходом в продакшн настройте аутентификацию, TLS, мониторинг и политики резервного копирования.
Похожие материалы
Skype не запускается в Windows 10/11 — как исправить
Обслуживание электросамоката: безопасность и советы
Что такое Spotify Daylist и как его найти
7 способов сделать Spotify центром вечеринки
Контроллер Xbox One не работает — руководство по ремонту