MongoDB: CRUD‑операции и основы NoSQL
Краткое введение
MongoDB позволяет создавать современные базы данных, которые легко читаются и изменяются. Это документная NoSQL‑СУБД с открытым исходным кодом, доступная для большинства операционных систем.
Если вы изучали проектирование баз данных в университете, возможно, вы не проходили MongoDB и NoSQL в деталях. До конца 1990‑х большинство людей и не слышали о NoSQL, а активное распространение началось около 2009 года.
Важно: NoSQL не противопоставляет себя SQL в полном смысле — это семейство подходов к хранению данных, отличных от реляционных таблиц.
Что такое NoSQL?
SQL означает «structured query language» и применяется к реляционным базам, где данные хранятся в таблицах с фиксированными строками и колонками. Термин NoSQL чаще всего трактуется как «not only SQL» — то есть набор технологий, которые позволяют хранить и обрабатывать данные в нереляционных формах: документов, пар «ключ–значение», колонко‑ориентированных и графовых хранилищ.
Типы NoSQL‑систем (кратко):
- Документные (document) — MongoDB, CouchDB. Хранят документы с произвольными полями (обычно JSON/BSON).
- Ключ‑значение (key‑value) — Redis, Riak. Очень простая модель для быстрых операций по ключу.
- Колонко‑ориентированные (column) — Cassandra, HBase. Оптимизированы для аналитики и большого объёма данных.
- Графовые (graph) — Neo4j. Подходят для данных с насыщенными связями.
Когда NoSQL работает лучше: гибкая схема, масштабирование горизонтально, хранение вложенных структур. Когда не подходит: сложные транзакции или строгая целостность, когда нужна нормализованная реляционная модель.
Что такое MongoDB?
MongoDB — документная база данных. Документы хранятся в формате, совместимом с JSON (фактически используется бинарное представление BSON). Каждому документу автоматически присваивается уникальный идентификатор _id. MongoDB поддерживает все базовые CRUD‑операции и предоставляет гибкую схему: разные документы в одной коллекции могут иметь разные поля.
Ключевые особенности MongoDB (в одном предложении): гибкая схема, индексирование, масштабирование через шардинг, репликация, поддержка агрегаций и драйверы для основных языков программирования.
Установка и запуск MongoDB
Перед выполнением CRUD‑операций нужно установить MongoDB на локальную машину или воспользоваться облачным сервисом (MongoDB Atlas). После установки запустите сервер и подключитесь к нему с помощью драйвера вашего языка.
Пример запуска mongod (как в исходном тексте):
/Users/Administrator/mongodb/bin/mongod.exe --dbpath=/Users/Administrator/mongodb-data
Пояснения:
- Первая часть — путь к исполняемому файлу mongod.exe в папке bin. На вашей машине путь, вероятно, будет другим.
- Вторая часть (–dbpath) указывает на папку, где MongoDB будет хранить файлы базы данных. Эту папку нужно создать заранее и убедиться, что у процесса есть права чтения/записи.
После успешного запуска в логах вы увидите две важные строки — адрес прослушивания (обычно 127.0.0.1) и порт (по умолчанию 27017). Примеры логов:
{"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"}}
Эти значения понадобятся при настройке строки подключения.
Советы по установке:
- На Linux используйте дистрибутивные пакеты или официальный репозиторий MongoDB.
- На macOS удобно устанавливать через Homebrew.
- На Windows проверьте путь к mongod.exe и права на папку данных.
- Для production‑среды завершительно настройте systemd unit (Linux) или службу Windows.
Подключение и драйверы
Для работы с MongoDB из приложения используется клиент (драйвер). В примерах ниже используется Node.js‑драйвер и объект MongoClient.
Строка подключения к локальному серверу обычно выглядит так:
mongodb://127.0.0.1:27017
Пример подключения (из исходного текста):
// import mongodb and use destructuring to get the MongoClient function
const { MongoClient } = require("mongodb");
//the connection URL and the database that we intend to connect to
const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'user-manager';
//using the connect function on the MongoClient to connect to the MongoDB server
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) =>{
//check if connection was established
if (error){
return console.log('Could not connect to database');
}
//access the user-manager database
const db = client.db(databaseName);
//insert one user into the database
db.collection('users').insertOne({
name: 'John Doe',
age: '28'
}, (error,result) =>{
if (error){
return console.log('Could not create user');
}
console.log(result.ops);
})
})
Примечания по драйверам:
- Каждый язык (Node.js, Python, Java, C#, Go и т. д.) имеет собственный официальный драйвер от MongoDB.
- В новых версиях драйвера Node.js опция useUnifiedTopology используется для активации нового механизма обнаружения серверов и мониторинга.
- Альтернативы для быстрого прототипирования: mongosh — интерактивная оболочка для запросов.
CRUD‑операции — что это такое
CRUD — аббревиатура от create (создать), read (прочитать), update (обновить), delete (удалить). Это четыре базовые операции для любой базы данных.
Ниже идут практические примеры и пояснения для каждого типа операции в MongoDB.
Создание документа (Create)
В MongoDB есть два наиболее частых метода вставки:
- insertOne — вставляет один документ.
- insertMany — вставляет сразу несколько документов.
Когда использовать:
- insertOne — когда создаётся отдельная запись (например, регистрация пользователя).
- insertMany — когда нужно загрузить пачку данных (bulk load) или импортировать коллекцию.
Пример insertOne (из исходного текста):
// import mongodb and use destructuring to get the MongoClient function
const { MongoClient } = require("mongodb");
//the connection URL and the database that we intend to connect to
const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'user-manager';
//using the connect function on the MongoClient to connect to the MongoDB server
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) =>{
//check if connection was established
if (error){
return console.log('Could not connect to database');
}
//access the user-manager database
const db = client.db(databaseName);
//insert one user into the database
db.collection('users').insertOne({
name: 'John Doe',
age: '28'
}, (error,result) =>{
if (error){
return console.log('Could not create user');
}
console.log(result.ops);
})
})
Пример вывода (консоль):
[ { name: 'Peter Davis', age: '32', _id: 60772f869475e84740003c45 } ]
Комментарий: MongoDB автоматически сгенерирует поле _id, если оно не задано явно.
Советы по вставке:
- Для массовых операций используйте insertMany с опцией ordered: false, чтобы ошибки в одном документе не останавливали вставку остальных.
- Валидируйте поля до вставки (несколько способов: в приложении, с помощью схем в ODM, либо через встроенную валидацию коллекций MongoDB).
Чтение документа (Read)
Основные методы чтения:
- find — возвращает курсор и используется для множественного чтения.
- findOne — возвращает первый найденный документ.
Пример findOne (из исходного текста):
// import mongodb and use destructuring to get the MongoClient method
const { MongoClient } = require("mongodb");
//the connection URL and the database that we intend to connect to
const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'user-manager';
//using the connect function on the MongoClient to connect to the MongoDB server
MongoClient.connect(connectionURL, { useUnifiedTopology: true }, (error, client) =>{
//check if connection was established
if (error){
return console.log('Could not connect to database') ;
}
//create the user-manager database
const db = client.db(databaseName);
//finding one user into the database
db.collection('users').findOne({name: 'Peter Davis'}, (error, user) => {
if (error){
return console.log('Could not find user');
}
console.log(user);
})
});
Пример вывода:
{ _id: 60772f869475e84740003c45, name: 'Peter Davis', age: '32' }
Полезные приёмы чтения:
- Для поиска по _id используйте ObjectId‑тип (в драйвере Node.js: new ObjectID(idString)).
- Индексируйте поля, по которым часто ищут, чтобы ускорить запросы.
- Используйте проекции, чтобы возвращать только нужные поля: find({}, { projection: { name: 1, age: 1 } }).
Обновление документа (Update)
Два основных метода:
- updateOne — обновляет первый попавшийся документ, соответствующий фильтру.
- updateMany — обновляет все документы, соответствующие фильтру.
Пример updateOne (из исходного текста):
//Update a user's age
db.collection('users').updateOne({ name: "Peter Davis"},
{
$set: {
age: '24'
}
})
Замечания:
- Операторы обновления ($set, $inc, $push и т. д.) модифицируют существующие поля и создают новые при необходимости.
- Если вы передаёте документ без операторов ($set и т. п.), MongoDB заменит документ целиком.
- Для атомарных операций используйте соответствующие операторы ($inc для инкремента и т. п.).
Удаление документа (Delete)
Методы удаления:
- deleteOne — удаляет первый документ, соответствующий фильтру.
- deleteMany — удаляет все документы по фильтру.
Пример deleteOne (из исходного текста):
//delete a document
db.collection('users').deleteOne({ name: 'Peter Davis'})
Удаление просто выполняется, но будьте осторожны: удалённые документы восстановить легко не получится без резервных копий.
Когда MongoDB не подходит
Контрпримеры и случаи, когда MongoDB может быть не лучшим выбором:
- Нужна строгая реляционная целостность (много‑табличные транзакции, жёсткая нормализация). Хотя MongoDB поддерживает транзакции в репликасете, сложные реляционные схемы всё ещё лучше подходят для реляционных СУБД.
- Очень сложные аналитические запросы с JOIN‑подобной логикой на больших объёмах данных — иногда эффективнее использовать колоночные хранилища.
- Требования соответствия (compliance) с конкретными реляционными стандартами — в таких случаях архитектура и процесс согласования могут потребовать реляционной базы.
Альтернативные подходы
Если MongoDB не подходит, рассмотрите:
- PostgreSQL — реляционная СУБД с расширениями JSONB для хранения документов.
- Cassandra — для высокопроизводительного распределённого хранения и записи.
- Redis — для быстрых key‑value сценариев и кэширования.
- ElasticSearch — для поисковых задач и аналитики по тексту.
Практическая мини‑методология работы с MongoDB
- Определите модель данных: документы, вложенные объекты или ссылки между коллекциями.
- Выберите ключи и индексы для ускорения запросов.
- Настройте окружение: развёртывание сервера/реплики/шардирования в зависимости от нагрузки.
- Реализуйте CRUD в приложении через драйвер и проведите нагрузочное тестирование.
- Настройте мониторинг и резервное копирование.
Фактбокс: ключевые значения и понятия
- Стандартный порт MongoDB: 27017
- Локальный адрес по умолчанию: 127.0.0.1
- Формат документов: BSON (Binary JSON)
- Типы NoSQL: документные, ключ‑значение, колонко‑ориентированные, графовые
- Примеры методов: insertOne/insertMany, find/findOne, updateOne/updateMany, deleteOne/deleteMany
Ролевые чеклисты
DevOps:
- Установить mongod как службу.
- Настроить мониторинг (логи, метрики, оповещения).
- Организовать резервное копирование (mongodump/mongorestore или snapshot хранилища).
- Настроить сеть: firewall, bindIp, TLS.
Backend разработчик:
- Выбрать драйвер и версию, совместимую с сервером.
- Реализовать схему документов и валидацию на уровне приложения.
- Покрыть CRUD тестами и проверить обработку ошибок.
DBA / архитектор данных:
- Проанализировать индексы и планы выполнения.
- Планировать шардирование при высоких объёмах данных.
- Настроить репликацию для отказоустойчивости.
QA:
- Проверить корректность CRUD операций в edge‑кейcах (пустые поля, большие документы, конфликтные обновления).
- Проверить восстановление из резервной копии.
SOP: быстрый рабочий порядок для добавления пользователей
- Убедиться, что mongod запущен и доступен (127.0.0.1:27017).
- Подключиться через драйвер и получить db = client.db(‘user-manager’).
- Проверить наличие коллекции users, при необходимости создать индексы.
- Вставить данные через insertOne/insertMany.
- Проверить результат через findOne.
- При ошибках смотреть логи mongod и права на папку данных.
Security hardening — быстрое руководство
- Включите аутентификацию: создайте администратора и используйте роли.
- Ограничьте bindIp — слушать только нужные интерфейсы.
- Используйте TLS для шифрования трафика между приложениями и сервером.
- Применяйте принцип наименьших привилегий в ролях пользователей.
- Регулярно обновляйте MongoDB до поддерживаемой версии.
Конфиденциальность и соответствие требованиям (GDPR)
- Храните персональные данные с минимально необходимым набором полей.
- Реализуйте удаление и анонимизацию при запросах субъектов данных.
- Документируйте политики хранения и сроки удаления данных.
- Логи и бэкапы тоже могут содержать персональные данные — учитывайте их при сохранении и удалении.
Миграция и совместимость
Советы при переходе с реляционной базы на MongoDB:
- Пересмотрите модель данных: в MongoDB вложенные документы часто заменяют JOIN.
- Определите набор запросов и оптимизируйте структуру под наиболее частые операции.
- Планируйте миграции партиями и тестируйте на тестовом окружении.
- Проверьте совместимость драйверов и формат данных (даты, бинарные поля).
Пример простого рабочего сценария с командной оболочкой
- Запуск сервера:
mongod –dbpath /path/to/mongodb-data
- Дамп базы данных:
mongodump –db user-manager –out /backups/user-manager-YYYYMMDD
- Восстановление:
mongorestore –db user-manager /backups/user-manager-YYYYMMDD/user-manager
(Команды mongodump/mongorestore используются в целях резервного копирования и восстановления. Убедитесь, что версии инструментов совместимы с версией сервера.)
Decision tree для выбора операции (Mermaid)
flowchart TD
A[Нужно создать запись?] -->|Да| B[insertOne/insertMany]
A -->|Нет| C[Нужно читать данные?]
C -->|Да| D[find/findOne]
C -->|Нет| E[Нужно обновлять?]
E -->|Да| F[updateOne/updateMany]
E -->|Нет| G[Нужно удалять?]
G -->|Да| H[deleteOne/deleteMany]
G -->|Нет| I[Переосмыслить задачу]Частые ошибки и как их избежать
- Отсутствие индексов: приводит к медленным запросам. Решение — проанализировать slow query log и добавить индексы.
- Неправильная структура документов: слишком большие документы усложняют обновления. Решение — нормализация или разделение на поддокументы.
- Недостаточное резервное копирование: потеря данных. Решение — регулярные дампы/снепшоты и тесты восстановления.
Критерии приёмки
- CRUD API выполняет операции без ошибок в 95+% тестовых запросов (функциональные тесты).
- Время ответа для основных операций укладывается в требуемые SLA (определяется проектом).
- Документы валидируются до записи, отсутствуют неконсистентные записи.
- Резервное копирование выполняется и проверяется восстановлением на тестовом стенде.
Сводка
MongoDB — мощный инструмент для гибкого хранения документов и быстрых итераций над данными. Базовые операции CRUD просты в освоении: insert, find, update и delete. Однако при переходе в production важно продумать безопасность, индексацию, резервное копирование и структуру данных в соответствии с рабочими нагрузками.
Важно: при проектировании всегда ориентируйтесь на реальные запросы приложения — модель данных должна ускорять наиболее частые операции.
Изображение: Alexander Sosluev / Wikimedia Commons
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone