Введение в MongoDB

Illustration of a large wall of varied shelves filled with books, ornaments, a TV, potted plants, and scattered personal items, depicted in a stylized, monochromatic color scheme with orange accents. Illustration of a large wall of varied shelves filled with books, ornaments, a TV, potted plants, and scattered personal items, depicted in a stylized, monochromatic color scheme with orange accents.

В этой статье я хочу вам рассказать, почему вообще Mongo и стоит ли вам смотреть в ее сторону.

Для начала пару слов о моем опыте с ней. Попробовал я ее первый раз года четыре назад, когда она стала модная и все хотели ее попробовать, потому что NoSQL это то, что нужно любому стартапу!!! (на самом делел нет, читайте дальше) Но тогда дело далеко не зашло, побаловался, даже в каком-то из MVP ее применили, но в продакшн дело не пошло. С тех пор я ее, можно сказать, позабыл. Однако полтора года назад я устроился в компанию, где MongoDB активно используется. Там была развестистая микросервисная архитектура и один из микросервисов, весьма не микро, использовал как раз эту базу данных. Тут я вкусил ее по полной. Испытал и чувство наслаждения от того, как все легко меняется, и взрывы гнева от того, что неожиданности в ее поведении порой были слишком неожиданными. Теперь же я работаю в другом месте и Монга у нас используется с полной осознанностью с моей стороны и прикасаюсь я к ней ежедневно, можно даже сказать, ежечасно.

Итак, давайте разберем, почему вам стоит рассмотреть использование MongoDB в вашем проекте.

1. Отсутствие схемы.

Это самое очевидное преимущество. Если вы работаете над новым стартапов, в которым бизнес-модель еще не до конца ясна и с большой вероятностью проект до выхода на рынок претерпит множество изменений, в том числе на уровне организации данных - посмотрите в сторону NoSQL решений, в частности на Монгу. Все дело в том, что в отличие от моего горячо любимого PostgreSQL в Монге просто нет необходимости создавать таблицы, менять их схемы, создавать миграции, заботиться о типах данных. Однако тут будьте осторожны. Очевидный плюс этого пункта, что вам гораздо проще создавать новые таблицы, добавлять и убирать поля. Настолько просто, что в Mongoid (ORM для MongoDB) вы просто добавляете в вашу модель строчку а-ля field :text, type: String и все, при следующей записи в бд у нового элемента будет это поле. Если же вы вставляете данные без ORM - то вам и никакие "строчки" не нужны - просто пихайте, что душе угодно. Но тут же и темная сторона этой силы. Вы не можете быть вполне уверены, что в конкретном документе у вас есть конкретное поле. (примечание: документами в MongoDB называются записи в коллекции). Т.е. если раньше у вас не было поля text и вы добавили несколько записей, а потом добавили это поле и добавили еще записи - в старых записях у вас этого поля, конечно же, не появится. Спасибо Mongoid, он сделает вид, что такое поле есть и у них и просто вернет значение null.

2. Легкость горизонтального масштабирования.

Горизонтальное масштабирование требуется когда вам необходимо запихнуть в базу данных информации больше, чем диск на вашем сервере. Все, что связано с горизонтальным масштабированием является визитной карточкой любой NoSQL базы данных. Дальше они уже соревнуются в том, у кого выше надежность, у кого быстрее запись, у кого быстрее чтение и т.д. На момент написания этой статьи в PostgreSQL нет встроенного механизма горизонтального масштабирования. Есть сторонние проприетарные решения (не могу не упомянуть компанию Citus, они делают прекрасную работу). В MongoDB же это делается предельно просто, а статей про это написано много, и механизмы репликации вкупе с шардированием на ней работают прекрасно. Кроме того можно как позволить балансировщику автоматически выбирать, в какой шард складывать конкретные докуенты, так и задать правила относительно какого-то поля или набора болей.

3. Богатая функция аггрегации.

Язык SQL очень богатый и всем привычный, камней бросать я в него не стану. Однако то, как позволяет получать данные Монга однозначно заслуживает похвалы. Тут вам и map-reduce, и группировки по сложным условиям, и переформатирование документов на лету, и получение случайных документов, и сортировки. В общем все то, что вы можете выжать из SQL БД, плюс возможность записывать все это в формате pipeline'ов и с более читаемым синтаксисом.

Вот один из многих примеров из документации:

sql

SELECT cust_id,
       SUM(price) as total
FROM orders
WHERE status = 'A'
GROUP BY cust_id
HAVING total > 250

mongo

db.orders.aggregate( [
   { $match: { status: 'A' } },
   {
     $group: {
        _id: "$cust_id",
        total: { $sum: "$price" }
     }
   },
   { $match: { total: { $gt: 250 } } }
] )

Пример MongoDB справа хоть и чуть более многословный, но гораздо более адекватно структурированый. Если вы только пришли с SQL базы данных, потребуется какое-то время на привыкание, но потом привыкаешь и возвращаться не хочется.

4. Создана для денормализации.

В MongoDB принято хранить данные так, как вам это удобно. В SQL базах данных всегда (примечание: на самом деле нет, стоит всегда думать головой и не воспринимать слово "всегда" как закон) стоит заботиться об организации данных, чтобы таблицы были нормализованные, а запросы строить так, чтобы они могли левой пяткой глаз почесать, но данные достать. В Монго если вам неудобно, в каком формате или в каком месте лежат данные - вы с чистой совестью можете их или переместить, потому что отсутствие схемы это подразумевает, или просто продублирвать данные в нужное место. Т.е. фактически у вас может быть одно и то же поле с одними и теми же данными, но в разных коллекциях. Или два поля в одной коллекции, а плюс к ним еще одно поле, которое является композицией первых двух. Но это опять таки та сила, которую следует применять с умом. Если вы будете неконтролируемо плодить поля в документах, поддержка на уровне понимания разработчиком сущности будет становиться все труднее и труднее.

5. Простой формат индексов.

Индексы в MongoDB называются предельно понятно и их использование практически лишено подводных камней. Например в Постгресе если у вас есть b-tree индекс на одно поле и gist индекс на другое - при запросе, который использует оба этих индекса, использоваться будет только один из них. В Монге таких сюрпризов меньше.

Заключение

Несомненно MongoDB не серебряная пуля. В ней есть свои неожиданные подводные камни. Например она автоматически не отрубает медленные запросы и они продолжают висеть, пока вы их не закроете саомостоятельно. Еще вы можете испытать низкую производительность при count запросе на больших коллекциях. Но это все вещи, которые ты однажды узнаешь и потом просто помнишь о них, потому что жить они не сильно мешают. Я не агитирую всех уходить с SQL БД и переводить продакшн проекты на Монгу, но если вы стоите перед выбором, какую базу данных взять для нового проекта - подумайте о ней. Если все-таки не решитесь экспериментировать с NoSQL решением - тогда берите PostgreSQL. Они очень динамично развиваются, у них есть частично-nosql решение в виде json полей в таблице, огромное количество документации и прекрасная производительность. В общем не пожалеете. Но это тема для другой статьи.