Базы данных
MongoDB: документная БД в продакшне
Когда Forbes переводил сайт на новую платформу, им нужна была БД для статей с непредсказуемой структурой метаданных. 30 лет назад статья - текст и автор. Сегодня - текст, автор, теги, SEO meta, embed-коды, A/B варианты заголовков, версии перевода. MongoDB позволила менять схему без болезненных миграций.
- **Cisco**: MongoDB для IoT аналитики - 500 миллионов событий в день с устройств по всему миру
- **Adobe Experience Manager**: документная модель для управления контентом миллионов медиа-файлов
- **eBay**: MongoDB для системы листингов - гибкая схема обрабатывает разные типы товаров с уникальными атрибутами
Документная модель данных
MongoDB хранит данные как BSON (Binary JSON) документы в коллекциях. BSON расширяет JSON: добавляет типы Date, ObjectId, Binary, Decimal128. ObjectId - 12-байтный идентификатор, включающий timestamp создания, что позволяет сортировать по времени без дополнительного поля.
Ключевое решение в data modeling: **embed vs reference**. Если данные читаются вместе - embed (вложенный документ). Если данные часто обновляются отдельно или их размер неограничен - reference. Airbnb вложила фотографии листинга в документ (читаются вместе), но отзывы - в отдельную коллекцию (их может быть тысячи).
Правило 16MB: документ MongoDB ограничен 16MB. eBay обнаружила это жёстко: коллекция bid_history накапливала ставки прямо в документе лота. После нескольких тысяч ставок документ достигал лимита. Решение: вынести ставки в отдельную коллекцию с reference на лот.
Когда правильнее использовать reference вместо embed в MongoDB?
Aggregation Pipeline
Aggregation pipeline - механизм аналитики в MongoDB. Данные проходят через цепочку стадий: $match (фильтрация), $group (агрегация), $sort, $lookup (join), $project (преобразование), $unwind (разворачивание массивов). MongoDB выполняет pipeline на стороне БД - данные не гоняются в приложение.
$lookup в MongoDB - аналог JOIN, но дорогой без индекса. MongoDB Atlas автоматически предлагает создать нужные индексы через Performance Advisor при медленных запросах.
Что делает стадия $unwind в aggregation pipeline?
Индексы в MongoDB
MongoDB поддерживает несколько типов индексов. Single field - базовый B-Tree. Compound index - по нескольким полям, ESR rule (Equality-Sort-Range) определяет порядок полей. Multikey index - для массивов. Text index - полнотекстовый поиск. Geospatial - 2dsphere для координат.
Для запроса find({ country: 'US', age: { $gt: 18 } }).sort({ name: 1 }) какой индекс оптимален по ESR?
Шардинг и MongoDB Atlas
MongoDB шардинг делит коллекцию на chunks и распределяет их по shard серверам. Shard key определяет распределение документов. Hashed shard key равномерно распределяет write нагрузку - нет горячих шардов. Range sharding удобен для range queries, но создаёт риск hotspot при монотонно возрастающем ключе.
MongoDB Atlas - managed сервис, используемый SEGA, Toyota, Forbes. Atlas Search (Lucene под капотом) добавляет полнотекстовый поиск без отдельного Elasticsearch. Atlas Vector Search - для RAG приложений и semantic search без дополнительной инфраструктуры.
MongoDB не поддерживает транзакции, поэтому не годится для финансовых данных
MongoDB поддерживает ACID транзакции между несколькими документами и коллекциями с версии 4.0. Brex и другие fintech компании используют MongoDB в продакшне.
Это устаревший миф из эпохи MongoDB 2.x. Современный MongoDB 6.x - полноценная ACID БД, хотя multi-document транзакции в нём дороже по производительности, чем в PostgreSQL.
Почему монотонно возрастающий shard key (например, timestamp) проблематичен?
Ключевые идеи
- **Embed vs Reference**: embed для данных, читаемых вместе; reference для unbounded arrays (лимит 16MB на документ)
- **Aggregation Pipeline**: $match -> $unwind -> $lookup -> $group -> $sort - аналитика на стороне БД без лишнего трафика
- **ESR Rule**: порядок полей в compound index: Equality, Sort, Range - нарушение порядка делает индекс неэффективным
Связанные темы
MongoDB использует концепции, общие для всех document databases:
- Шардинг — MongoDB sharding - практический пример горизонтального партиционирования данных
- Индексы B-Tree — MongoDB использует B-Tree для всех индексов кроме hashed и text
- Polyglot Persistence — MongoDB часто комбинируется с Redis и Elasticsearch в одном стеке
Вопросы для размышления
- Приложение для блогов: посты, комментарии, лайки, теги. Что embed, что reference, и почему?
- Когда aggregation pipeline в MongoDB предпочтительнее, чем выгрузить данные и обработать в Python?
- MongoDB Atlas предлагает Vector Search. Как это меняет архитектуру AI-приложений с RAG?