// Engineering Log
Базы данных: Часть 6 — MongoDB
Опубликовано 21.09.2026
// Быстрый маршрут
Эта статья относится к теме Серверы и инфраструктура.
MongoDB — документоориентированная база данных. Вместо таблиц со строками она хранит коллекции документов в формате BSON — двоичном варианте JSON с дополнительными типами (даты, двоичные данные, десятичные числа). Документ может содержать вложенные объекты и массивы, а документы одной коллекции не обязаны иметь одинаковый набор полей.
Лицензия
MongoDB Community Server — версии, выпущенные начиная с 16 октября 2018 года, — распространяется под лицензией SSPL (Server Side Public License). Она разрешает бесплатно использовать MongoDB в своих приложениях, в том числе коммерческих, но требует раскрыть исходный код всей обвязки сервиса, если вы предоставляете саму MongoDB третьим лицам как услугу. Open Source Initiative не признаёт SSPL открытой лицензией, поэтому формально MongoDB не является открытым ПО. Драйверы для языков программирования распространяются под Apache 2.0.
Для компании, которая просто использует MongoDB как базу своего приложения, SSPL ограничений не создаёт. Если требуется именно открытая лицензия, есть FerretDB — о нём ниже.
Поддерживаемые ветки на сентябрь 2026 года — 7.0 и 8.0, последняя стабильная — 8.3. Устанавливать стоит последнюю стабильную версию: так рекомендует документация.
Документная модель
Пример документа заказа:
{
"_id": ObjectId("66f1c2a4e13b5a0012345678"),
"number": "2026-0915",
"customer": { "name": "ООО «Ромашка»", "inn": "7700000000" },
"items": [
{ "sku": "A-100", "qty": 2, "price": NumberDecimal("1500.00") },
{ "sku": "B-200", "qty": 1, "price": NumberDecimal("4200.00") }
],
"status": "paid",
"created_at": ISODate("2026-09-15T10:12:00Z")
}В реляционной базе те же данные заняли бы три таблицы — заказы, клиенты, позиции — и для чтения заказа понадобились бы соединения. В MongoDB заказ читается одним запросом целиком. В этом главное преимущество документной модели: данные, которые приложение всегда читает и изменяет вместе, лежат вместе.
Операция над одним документом в MongoDB атомарна. Поэтому хорошо спроектированная схема, где связанные данные вложены в один документ, часто вообще не требует транзакций.
Когда документная модель оправдана
- Данные естественно представлены в виде вложенных объектов: заказ с позициями, статья с блоками содержимого, профиль с настройками.
- Структура записей различается: каталог товаров, где у телефона и у дивана разный набор характеристик, журналы событий из разных источников.
- Схема часто меняется на ранней стадии продукта: новое поле можно начать записывать без миграции всей коллекции.
- Нужна горизонтальная масштабируемость: шардирование встроено и распределяет коллекцию по нескольким серверам.
Когда лучше выбрать реляционную базу
- Данные сильно связаны между собой: учёт, где документы, контрагенты, склады и проводки ссылаются друг на друга. Соединения в MongoDB выполняются через
$lookupв конвейере агрегации, и при большом числе связей это сложнее и медленнее, чемJOINв PostgreSQL. - Важна строгая целостность: внешние ключи, ограничения, проверки на уровне базы — сильная сторона SQL-СУБД.
- Много аналитических запросов по произвольным полям: SQL для этого удобнее.
- Нужны просто JSON-поля в обычной базе: PostgreSQL с типом
jsonbи индексами GIN закрывает многие задачи, ради которых выбирают MongoDB, и оставляет все возможности SQL.
Частая ошибка — выбрать MongoDB из-за «отсутствия схемы». Схема в приложении всё равно есть, просто она не описана в базе. Когда код меняется, в коллекции остаются документы старого формата, и приложение должно уметь с ними работать.
Проверка схемы
Чтобы база сама не принимала документы неправильной структуры, в MongoDB есть проверка по JSON Schema:
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["number", "customer", "items", "status", "created_at"],
properties: {
number: { bsonType: "string" },
status: { enum: ["new", "paid", "shipped", "cancelled"] },
items: { bsonType: "array", minItems: 1 },
created_at: { bsonType: "date" }
}
}
},
validationLevel: "strict", // проверять все вставки и изменения
validationAction: "error" // отклонять неверные документы; "warn" — только записывать в журнал
})Для существующей коллекции правила добавляются командой collMod. Режим validationLevel: "moderate" проверяет только новые документы и изменения уже корректных — это удобно при постепенном наведении порядка в старых данных.
Индексы
Без индекса MongoDB просматривает всю коллекцию. Индексы бывают по одному полю, составные, по элементам массивов, текстовые, геопространственные, с ограниченным временем жизни (TTL — документы удаляются автоматически), уникальные.
db.orders.createIndex({ status: 1, created_at: -1 })
db.sessions.createIndex({ created_at: 1 }, { expireAfterSeconds: 86400 }) // TTL: удалять через сутки
Для составных индексов в документации MongoDB есть правило ESR: сначала поля, по которым ищут точное совпадение (Equality), затем поля сортировки (Sort), затем поля с диапазоном (Range). Использует ли запрос индекс, показывает explain("executionStats").
Набор реплик
В рабочей среде MongoDB запускают не одним сервером, а набором реплик (replica set): один основной узел принимает запись, вторичные получают копию данных. Если основной узел выходит из строя, оставшиеся автоматически выбирают новый. Рекомендуемый минимум — три узла.
Набор реплик нужен не только для отказоустойчивости. Многодокументные транзакции (с версии 4.0) и потоки изменений (change streams) работают только в наборе реплик или шардированном кластере — на одиночном сервере они недоступны. Поэтому даже для разработки иногда запускают набор реплик из одного узла.
Безопасность
С версии 3.6 MongoDB по умолчанию принимает соединения только с локального адреса, но проверка паролей по умолчанию выключена. Открытые в интернет базы без авторизации много лет массово находят автоматические сканеры: данные удаляют и оставляют записку с требованием выкупа.
Минимум для рабочей установки в mongod.conf:
net:
bindIp: 127.0.0.1,10.0.0.5 # локальный и внутренний адрес, не публичный
security:
authorization: enabledПеред включением авторизации нужно создать администратора, а для приложения — отдельного пользователя с правами только на свою базу (роль readWrite). Порт 27017 закрывают межсетевым экраном; как и с Redis, при запуске в Docker его не публикуют на все интерфейсы.
Резервное копирование
Для небольших и средних баз подходит утилита mongodump из пакета MongoDB Database Tools (он устанавливается отдельно от сервера):
mongodump --uri="mongodb://backup:ПАРОЛЬ@127.0.0.1:27017/?authSource=admin" \
--oplog --gzip --archive=/backup/mongo-$(date +%F).archive.gz
mongorestore --gzip --archive=/backup/mongo-2026-09-21.archive.gz --oplogReplayПараметр --oplog работает только на узле набора реплик и включает в копию изменения, сделанные во время выгрузки, — получается согласованная копия на момент окончания. Для шардированного кластера перед выгрузкой нужно остановить балансировщик (sh.stopBalancer()) и распределённые транзакции. Для больших баз mongodump работает медленно, и их копируют снимками файловой системы или специализированными средствами.
FerretDB — открытая альтернатива
FerretDB — проект под лицензией Apache 2.0, который принимает запросы по протоколу MongoDB и выполняет их в PostgreSQL с расширением DocumentDB. Приложение подключается к нему обычным драйвером MongoDB. Разработчики позиционируют его как замену MongoDB 5.0 и новее во многих случаях, но совместимость неполная: перед переходом нужно проверить, какие команды и операторы использует ваше приложение. Преимущество — данные хранятся в PostgreSQL, который уже умеют администрировать и резервировать.
Достоинства
- Документная модель совпадает со структурой объектов в коде, связанные данные читаются одним запросом.
- Гибкая схема при необходимости дополняется проверкой по JSON Schema.
- Встроенная репликация с автоматическим переключением.
- Шардирование для распределения данных между серверами.
- Развитый язык запросов и агрегации: фильтрация, проекции, конвейеры агрегации, полнотекстовый и геопоиск.
Недостатки
- Лицензия SSPL не признаётся открытой.
- Соединения данных через
$lookupсложнее и медленнее реляционныхJOIN. - Транзакции доступны только в наборе реплик и заметно нагружают базу; их стоит применять как исключение.
- Объём данных обычно больше, чем в реляционной базе: имена полей хранятся в каждом документе. Размер одного документа ограничен 16 МБ.
- Администрирование кластера: набор реплик и тем более шардированный кластер сложнее в обслуживании, чем одиночный сервер PostgreSQL.
MongoDB хорошо подходит для данных, которые естественно укладываются в документы и меняют структуру, и для систем, которым нужна горизонтальная масштабируемость. Для учётных систем со множеством связей, строгой целостностью и аналитикой на SQL надёжнее выбрать PostgreSQL — возможно, с полями jsonb для той части данных, которой действительно нужна гибкость.
// Похожая задача
Если у вас похожая ситуация
Эта статья относится к одной из рабочих тем. Можно продолжить чтение по теме, перейти на главную, чтобы понять, чем я занимаюсь, или сразу открыть услуги.
Тема статьи
Серверы и инфраструктура
VPS, Linux, веб-стек, миграции, хостинг, базы данных и базовая эксплуатация.
Часто с этим приходят
- Перенести сайт или сервис на новый сервер
- Настроить Linux, Nginx, базу данных и бэкапы
- Разобраться, почему всё работает нестабильно
// Следующий шаг
Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.
Открыть услуги// Contact
Нужна помощь?
Свяжись со мной и я помогу решить проблему
Написать в TelegramОтвечаю в течение рабочего дня (03:00–13:00 GMT)
Или оставьте заявку здесь:
// Related