как узнать версию mongodb

Подумываете об использовании MongoDB?

Будет ли MongoDB правильным выбором для вашего приложения?

Выбор базы данных — важный этап разработки приложения. Неправильный выбор может негативно сказаться как на процессах разработки и сопровождения вашего продукта, так и привести к снижению производительности.

В принципе, можно использовать любую базу данных, и она будет работать. Но одна база данных лучше работает с одним типом рабочей нагрузки, а другая с другим.

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

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

MongoDB работает с JSON-документами и разработчикам это нравится

Базовым компонентом MongoDB является документ, очень похожий на JSON. Технически это BSON, который содержит некоторые дополнительные данные (например, datetime), которые недопустимы в JSON.

Мы можем рассматривать документ как запись в реляционной базе данных. Документы помещаются в коллекции, которые соответствует концепции таблиц в реляционной базе данных.

JSON-документы очень популярны среди программистов и используются при разработке веб-сервисов, приложений и для обмена данными. Работать с базой данных со встроенной поддержкой таких данных может быть действительно эффективно.

Разработчики часто выбирают MongoDB, потому что ее можно начать использовать без специальных знаний об администрировании и проектировании баз данных, а также без изучения сложного языка запросов. Язык запросов MongoDB также представлен в формате JSON документов.

Разработчики могут легко создавать, сохранять, запрашивать и изменять JSON-документы. Здорово! Обычно это значительно ускоряет разработку.

В MongoDB нет схемы

Вы знакомы с реляционными базами данных? Наверняка да, ведь реляционные базы данных используются и изучаются уже очень давно и в школе и университете. В настоящее время на рынке это наиболее широко используемый тип баз данных.

Реляционная схема требует предопределенной и фиксированной структуры таблиц. Каждый раз, когда вы добавляете или изменяете столбец, вам необходимо выполнить DDL-запрос, и приложить дополнительные усилия, чтобы изменить код вашего приложения для работы с новой структурой. В случае значительных изменений, требующих изменения нескольких столбцов и/или создания новых таблиц, изменения в приложении могут быть весьма значительными. Отсутствие схемы в MongoDB означает, что ничего из этого не требуется. Вы просто добавляете документ в коллекцию и все. Например, у вас есть коллекция с данными пользователя. Если в какой-то момент вам нужно добавить новое поле «date_of_birth», вы просто начинаете работать с новыми JSON-документами с дополнительным полем. И все. Нет необходимости менять что-либо в схеме.

Вы также можете вставлять в одну и ту же коллекцию совершенно разные JSON-документы, представляющие разные сущности. Технически это осуществимо, но все же так делать не рекомендуется.

MongoDB также значительно сокращает цикл разработки приложения по нетехнической причине — устраняется необходимость координации миграции изменений схемы базы данных с DBA. Нет необходимости ждать, пока команда DBA еще раз все проверит и выпустит релиз в продакшн (с планами отката), что, как правило, потребует еще и некоторого простоя.

В MongoDB нет внешних ключей, хранимых процедур и триггеров. JOIN поддерживается, но не приветствуется

Проектирование реляционной базы данных должно осуществляться с учетом того, чтобы SQL-запросы могли выполнять различные JOIN для нескольких таблиц по определенным колонкам. Также необходимо предусматривать внешние ключи (foreign key) для контроля целостности данных и автоматических изменений в связанных полях.

Что насчет хранимых процедур? Хранимые процедуры могут быть полезны для встраивания в базу данных некоторой логики приложения для упрощения ряда задач или повышения безопасности.

А триггеры? Триггеры нужны для автоматического инициирования изменений данных при определенных событиях, таких как добавление / изменение / удаление строк. Они помогают управлять согласованностью данных и, в некоторых случаях, упростить код приложения. Но они отсутствуют в MongoDB. Так что имейте это в виду.

Примечание: честно говоря, есть агрегирование, которое может реализовать то же самое, что и LEFT JOIN, но это единственный случай.

Как жить без JOIN?

Соединение (JOIN) должно выполняться в коде вашего приложения. Если требуется выполнить JOIN двух коллекций, то сначала нужно прочитать первую, выбрать поле для JOIN и использовать его для запроса второй коллекции и т.д. Это кажется весьма дорогим с точки зрения разработки приложения и может привести к увеличению количества запросов. И это действительно так. Хорошая новость заключается в том, что в большинстве случаев вам не придется использовать JOIN.

Помните, что MongoDB — это база данных без схемы, не требующая нормализации. Если вы правильно спроектируете коллекции, то сможете встраивать (embed) и дублировать данные в одной коллекции без необходимости создания дополнительных коллекций. Таким образом, вам не придется выполнять соединение, потому что все данные, которые вам нужны, уже будут в одной коллекции.

Внешние ключи не поддерживаются. Но так как можно встраивать в одну коллекцию несколько документов, они вам просто не нужны.

Хранимые процедуры могут быть легко реализованы в виде внешних скриптов, написанных на любом языке программирования. Триггеры также реализуются снаружи с помощью Change Stream API.

Если у вас много коллекций, содержащих ссылки на поля, то в коде приложения вам придется реализовать много JOIN или выполнить множество проверок для обеспечения согласованности. Это все возможно, но потребует больших затрат на разработку. В этом случае MongoDB может оказаться неправильным выбором.

Очень просто развернуть репликацию и шардирование

MongoDB изначально разрабатывалась для работы в распределенных окружениях. Она была задумана как часть большого пазла. Для реализации репликации и шардирования сервер mongod может работать совместно с другими экземплярами mongod без использования каких-либо сторонних инструментов.

Replica Set (набор реплик) — это группа процессов mongod, которые обслуживают один и тот же набор данных, обеспечивая избыточность и высокую доступность. С оговорками, касающимися потенциально устаревших данных, вы также бесплатно получаете масштабируемость чтения. Для продакшн-решения всегда следует применять такую конфигурацию.

Sharding Cluster развертывается как группа из нескольких Replica Set с возможностью разделения и равномерного распределения данных по ним. В дополнение к избыточности, высокой доступности и масштабируемости чтения Sharding Cluster обеспечивает масштабируемость записи. Топология шардинга подходит для развертывания очень больших наборов данных. Количество шардов, которые вы можете добавить, теоретически не ограничено.

Читайте также:  как понять что девочка ревнует

Обе топологии можно изменить в любое время, добавив больше серверов и шардов. Что еще более важно, никаких изменений в приложении не требуется, поскольку каждая топология полностью прозрачна с точки зрения приложения.

И, наконец, развертывание таких топологий очень просто. Вначале вам придется потратить некоторое время, чтобы понять несколько основных концепций, но затем, в течение нескольких часов, вы сможете развернуть даже очень большой кластер с шардированием. В случае нескольких серверов вместо того, чтобы делать все вручную, вы можете автоматизировать многие вещи с помощью плейбуков Ansible или других подобных инструментов.

Дополнительные материалы:

В MongoDB есть индексы, и они очень важны

В MongoDB можно создавать индексы для полей JSON-документа. Индексы используются так же, как и в реляционных базах данных для ускорения выполнения запросов и уменьшения использования ресурсов компьютера: памяти, времени процессора и операций ввода-вывода в секунду (IOPS).

Для всех регулярно выполняемых запросов, операций изменения и удаления данных необходимо создавать необходимые индексы, которые помогут ускорить их выполнение.

MongoDB обладает очень мощными возможностями индексирования. Есть TLL-индексы, GEO Spatial — индексы для пространственных данных, индексы для элементов массива, частичные (partial) и разреженные (sparse) индексы. Если вы хотите подробнее изучить доступные типы индексов, вы можете обратиться к следующим статьям:

Создавайте все необходимые индексы для ваших коллекций. Они очень помогут вам улучшить общую производительность вашей базы данных.

MongoDB требует много памяти

MongoDB использует оперативную память для кэширования наиболее часто и недавно используемых данных и индексов. Чем больше этот кэш, тем лучше будет общая производительность, потому что MongoDB сможет быстрее извлекать большой объем данных. Кроме того, изменения данных происходят в памяти. Запись на диск выполняется асинхронно: сначала в файл журнала (обычно в пределах 50 мс), а затем в обычные файлы данных (один раз в минуту).

WiredTiger — наиболее популярный движок хранения данных, используемый в MongoDB. Раньше это был MMAPv1, но в последних версиях он больше не доступен. Движок хранения WiredTiger использует кэш памяти (WiredTiger Cache) для кэширования данных и индексов.

Помимо WTCache, для доступа к диску MongoDB использует кэш файловой системы. Это еще одна важная оптимизация, для которой также может потребоваться значительный объем памяти.

Кроме того, MongoDB использует память для управления клиентскими соединениями, выполнения сортировки в памяти, временных данных при выполнении пайплайнов агрегации и другого.

Будьте готовы обеспечить MongoDB достаточным объемом памяти.

Но сколько нужно памяти? Эмпирическим правилом является оценка размера «рабочего набора».

«Рабочий набор» — это данные, которые чаще всего запрашиваются вашим приложением. Типичное приложение работает с ограниченным объемом данных. При обычной работе ему не нужны все данные. Например, в случае с временными рядами (time-series data), скорее всего, вам нужно будет получить только последние несколько часов или дней. Только в редких случаях вам понадобится читать более старые данные. В таком случае в вашем рабочем наборе может будут храниться данные только за несколько дней.

Предположим, что ваш набор данных составляет 100 ГБ, и вы оценили ваш рабочий набор в 20%, тогда вам потребуется как минимум 20 ГБ для WTCache.

Так как по умолчанию для WTCache используется 50% памяти (обычно мы рекомендуем не увеличивать ее значительно), то на сервере должно быть 40 ГБ памяти.

Каждый случай индивидуален, и иногда бывает трудно правильно оценить размер рабочего набора. В любом случае, основная рекомендация заключается в том, что вы должны предоставить максимальное количество памяти, которое можете себе позволить. Это будет полезно для MongoDB.

В каких случаях использовать MongoDB?

На самом деле таких ситуаций очень много. Я видел использование MongoDB в самых разных приложениях.

Например, MongoDB подходит для следующих типов приложений:

Источник

Шпаргалка по mongodb: e-commerce, миграция, часто применяемые операции и немного о транзакциях

Миграция в mongodb

До версии 2.6

После выхода версии 2.6 в mongodb была добавлена новая система назначения прав пользователей на базы, отдельные коллекции. И, соответственно, при обновлении это нужно учитывать.

Собственно, само обновление:

2) После того как обновились до 2.6 нужно зайти в базу admin и выполнить несколько команд, которые проверят совместимость документов.

Для этого вначале надо создать пользователя «Администратор» в базе admin

4) После этого зайти в свою нужную базу, с которой собрались работать и к которой хотим подключиться, и создаем там пользователя.

Автоматически запись будет создана в базе admin в коллекции system.users
Просмотреть пользователей базы можно командой:

Ну и не забываем перегрузить после всего этого.

В ubuntu c этой версии сервис называется не mongodb а mongod а конфиг в /etc называется mongod.conf скорее всего, это связано с отсутствием обратной совместимости чтобы при обновлении не перепутать.

С 2.6 до 3.0 версии

О новой версии 3.0 и революционных изменениях в движке хранилища было уже написано много, не буду повторяться.

Для каждого компонента указываем версию при установке.

Смотрим версию mongodb :

Для смены в /etc/mongo.conf ставим опцию:

Подробнее про возможные опции связанные с новым хранилищем тут
И смотрим чтоб директория /var/lib/mongodb была пустой иначе mongodb не запустится, естественно перед этим для всех баз нужно сделать mongodump

Проверяем версию движка для хранилища:

Ищем storageEngine если wiredTiger то все нормально.

Теперь нужно импортировать базы, включая admin

Новое в PyMongo

Даже без обновления самой базы, не все будет работать как прежде. Из того, что сразу было замечено:

Запросы сравнения и логические

$gt больше чем
$gt выбирает те документы, где значение поля больше (>) указанного значения.

$gte больше или равно чем
$gte выбирает те документы, где значение поля больше или равно (>=) указанного значения.

Читайте также:  жк легенда героев адрес

$lt меньше чем
$lt выбирает те документы, где значение поля меньше ( указанного

$lte меньше или равно чем
$lte выбирает те документы, где значение поля меньше или равно ( указанного

$ne не равно
$ne выбирает документы, где значение поля не равно (! =) указанному значению.

$in проверка на вхождение

Пример с регулярным выражением

Для этого запроса предлагается составить два индекса:

$and оператор «и»
Оператор и проверяет присутствие всех перечисленных значений в искомых документах.

$not оператор отрицания
Проверяет чтобы в выборке не было документов, соответствующих условию.

Пример с регулярным выражением:

$nor оператор не или

Этот запрос в коллекции test найдет те документы в которых:

$type проверка BSON типа

Вернет следующие документы:

C 2.6 версии запрещено передавать только один элемент, будет возращена ошибка. Также, если передать больше трех аргументов, тоже выдаст ошибку, в предыдущих версиях лишние аргументы просто игнорировались.
$all выбрать соответствующие всем
Делает выборку больше чем по одному элементу массива.

$elemMatch
Используется когда нужно сравнить два и более атрибутов, принадлежащих одному поддокументу.
Проверяет, что в массиве есть элемент подпадающий под все условия.

Такой запрос будет соответствовать, например, следующему документу:

$ позиционный оператор
$ может использоваться в разных случаях. Когда мы не знаем под каким индексом лежит значение в массиве но хотим его использовать, то применяем «позиционный оператор»
Например, есть документы:

И мы хотим, чтобы после поиска по ним вывелось только одно значение, соответствующее запросу, а не весь документ, но заранее мы не знаем какое значение там стоит.

$slice находит диапазон
$slice — находит диапазон значений хранящихся в массиве.
Найти первые 10 событий:

Найти последние 10 событий:

Полнотекстовый поиск в Mongodb, regexp, индексы и пр.

Можно использовать название поля или подстановочный спецификатор:

При создании индекса для полнотекстового поиска надо учитывать язык, если это не английский.

Начиная с версии 2.6 появилась возможность задания текстового индекса сразу для многих языков.

MongoDB будет использовать указанный в документе язык при построении индекса. Язык указанный в документе перекрывает язык по умолчанию. Язык во встроенном документе переопределяет все остальные для индекса.

Также, есть возможность с помощью параметра language_override указывать поле с языком.
Например, для документов:

Индекс будет выглядеть таким образом:

Индексу можно назначать специальное имя < name: "name" >, например:

Имя удобно использовать для удаления индексов:

Через индекс можно ограничить кол-во записей в выдаче:

На выходе будет только один документ вместо двух, так как мы ограничили в индексе.
Пример индекса для Python :

Текстовый поиск

Сразу после появления текстового поиска в mongodb он осуществлялся с помощью runCommand например:

Поиск по нескольким словам:

Исключение поля из поиска через

i — Нечувствительность к регистру.
Аналог из PostgreSQL

Атомарные операторы (модифицирующие данные )

Как правило все эти модификаторы используются для операций обновления в db.test.update() и db.test.findAndModify()

$inc инкремент
Увеличивает или уменьшает поле на заданное значение

$mul мультипликативный инкремент
Умножает значение поля на заданную величину.

$rename переименование поля

$max обновляет если больше
$max обновляет поле, если указанное значение больше текущего значения поля.

$currentDate устанавливает текущую дату
Устанавливает значением поля текущую дату.

Изменения массивов

$addToSet добавляет значение, если его нет
Добавляет значение в массив, если его там еще нет, а если есть, то ничего не делает.

$pullAll удаляет все указанные
Удаляет все указанные элементы из массива.

$pull удаляет в соответствии с запросом

$push добавляет значения
Добавляет значения в массив.

$pushAll — считается устаревшим

$position указывает позицию вставки
Указывает с какого по счету элемента массива вставить значения.

О транзакциях в mongodb, уникальный индекс, двухфазный коммит

Уникальный индекс

Уникальный индекс в mongodb является причиной отклонить все документы, которые содержат повторяющиеся значения для индексированных полей.

Если все операции update() успешно выполнили запрос и нашли обновляемый документ прежде, чем любой из клиентов вставит свои данные, и нет уникального индекса на поле, то все операции обновления могут вставить данные.

Для предотвращения вставки в один и тот же документ несколько раз, нужно создать уникальный индекс на поле. Тогда одна из операций обновлений точно вставит новый документ. Остальные операции либо обновят недавно вставленный документ, либо не смогут выполнить операцию если попытаются вставить дублирующие значения.

По умолчанию unique является false в индексах MongoDB

Двухфазный коммит

Инициализация коллекций accounts и transactions
Вставляем в коллекцию accounts два документа соответственно для счетов А и В

В коллекцию transactions для каждого перевода средств вставляем документ с информацией о транзакции.

Где у нас есть следующие поля:

2) Обновление статуса транзакции до состояния pending
Меняем состояние нужной транзакции с initial на pending и устанавливаем текущую дату.

3) Изменение обоих счетов
Изменяем баланс у обоих документов средства, одному увеличиваем на количество, равное полю value из документа транзакции, а в поле pendingTransactions заносим _id транзакции (документа где хранится информация о транзакции).

4) Обновление транзакции до состояния applied
Обновляем документ с транзакцией и не забываем установить дату последнего изменения.

6) Обновление транзакции до состояния done
На этом двухфазный коммит завершён.

Откат двухфазного коммита

2) Отменяем транзакцию для обоих счетов
Возвращаем средства обратно на счет с которого переводили.

3) Устанавливаем состояние транзакции cancelled
Обновляем состояние с отменяемой до отмененной.

Двухфазный коммит и много приложений

6. Агрегационный фреймворк и JOIN-ы

И, как правило, всегда рекомендуется документы, которые могут участвовать в одном запросе, помещать в одну коллекцию.

А если потом есть желание разбить их на какие-то группы по определённым признакам, то различать их по одному из полей, например < type: 'news' >.

Но бывают случаи когда действительно надо взять несколько документов, у которых нет практически ничего общего, и объединить их в один документ.

Предположим, у нас есть две разновидности документов, в одной находятся пользователи и перечисляется группы к которым они относятся.

И есть документы в которых находятся статьи написанные этими пользователями.

Читайте также:  как понять что она скучает

Задача получить на выходе в одном документе пользователя, статьи которые он написал и группы в которых состоит. Конечно если бы мы это делали несколькими запросами, то все выглядело довольно просто.

Выбрать из блогов только те статьи, где пользователь, опубликовавший материал, состоит в группе «автор».

Примерный аналог c джойном из SQL если мы членство в группах храним в таблице:

Или если мы названия групп храним прямо в таблице user, если всё хранится в поле d типа jsonb. Селектами делается два списка — и дальше на них накладываются ровно те же условия:

Теперь попробуем повторить примерно то же самое с помощью pipe.

Теперь разберем по порядку что делает запрос. Запрос состоит из 7 частей.
Как правило, в справке по mongodb и статьях про pipeline приводят эту табличку. Она не совсем отражает смысл каждого оператора, но, имея её перед глазами, немного помогает ориентироваться в длинных цепочках, ну и не забывать, что порядок может быть абсолютно любой и повторяться каждый оператор может много раз.

Сначала мы находим все документы с которыми будем работать.

Следующим этапом группируем эти документы:

И завершающая часть:

Мы просто отфильтруем те документы, которые соответствовали предыдущему условию.
И теперь у нас есть документы, в которых указано какую статью написал каждый пользователь и в какой пользовательской группе он состоит.

7. Примеры

В основном здесь речь пойдет, скорее, о структуре документов чем о запросах. Как правило есть два основных подхода обычно:

Деревья, комментарии в Mongodb

Как правило, одна из самых распространенных задач — это различные древовидные структуры. Это и комментарии, и каталог товаров в интернет магазинах, и схемы хранения на складах, и много чего еще.

Рассмотрим пару простых примеров.
В виде субдокументов:

Сам по себе простой поиск по обоим вариантам будет работать достаточно эффективно.
Тем более, что по второму варианту можно создать индексы.
В некоторых случаях вариант с поддокументами нужен для хранения части информации, но в целом сами комментарии хранятся в поддокументах, такие варианты называют модным ныне словом «гибридная» схема.

Теперь рассмотрим несколько примеров работы с документами.
Удалить одного или несколько детей у родителя:

Добавить одного или несколько детей родителю:

Сформируем дерево из полученных документов:

Посчитаем количество товаров, которые относятся к каждой категории дерева с учетом всех вложенных категорий, при условии, что в каждом товаре хранится _id категории к которой он принадлежит:

Найдем путь к началу, зная _id категории, после чего останется в шаблоне просто фором пройтись по списку кортежей:

Теги, блоги

Ну и теперь отфильтруем:

Теперь все, что нам нужно — разделить область видимости сайта на ячейки и для каждой из них можно предоставлять свой контент.

Е-commerce и сложные фильтры в Mongodb

Наверное, одна из основных сложностей и задач веб-магазинов и различных учётов — это все-таки фильтры. Они нужны как для создания хитрых отчетов, так и для просто показа где что лежит на складе, ну и, банально, отфильтровать ноутбуки по диагонали, цене, производителю и прочему.

Последним случаем, из-за слишком большого объема материала, мы и ограничимся. Остальные рассмотрим в последующих публикациях.

Существует два вида фильтров, или, если хотите, способа организации контента в веб-магазине.

В первом случае, поскольку наличествующие атрибуты у нас просто текстовые поля, ни с чем не связанные, то нам нужно просто по ним сгруппировать документы — и всё. Но в таком случае при неправильном заполнении, а также при развитии учета, в магазине возникнут проблемы и придется все перезаносить.

Во втором случае нам надо для каждой категории товаров настроить свои фильтры и каждый из фильтров тем или иным способом привязать к характеристикам товаров (атрибутам).

Работа с фильтрами состоит из двух этапов:

Начнем с показа значений фильтра, если у нас настроена привязка фильтров к характеристикам товаров, тогда все выглядит довольно просто. И делается простым запросом:

Представить данные можно по разному, например, можно сделать древовидной таблицей, где первым уровнем будут названия фильтров, а вторым уровнем его характеристики.

Название => Диагональ
Характеристики=> 15.6 дюйма, 17 дюймов и тд.

Можно по другому представить, пойти как на мой взгляд немного более распространенным путем. Сделать подтаблицами по типу приходных и расходных накладных. Когда есть шапка документа с перечислением реквизитов и тд., и есть список товаров снизу.
Только в данном случае шапка — это название категории, для которой мы настраиваем фильтры, а список товаров — это список названий фильтров с атрибутами в одной из подчиненных таблиц.

В этом случае запрос будет немного посложнее и придется группировать данные. Это уже будет похоже на аналогичный запрос к получению фильтров из самих товаров, этот запрос и опишем.

У нас есть список товаров, у каждого есть список атрибутов хранящихся или в отдельных документах, или в нем самом в субдокументах. Визуально это может выглядеть примерно так.

После первого group мы получаем документы такого типа:

После второго group мы уже получаем окончательный вариант.

Теперь, когда мы уже имеем список фильтров, можно поискать по этим фильтрам. Поскольку мы ищем по субдокументам, то есть по характеристикам, то группируем по owner_id это _id документа к которому принадлежат характеристики.

На выходе получаем список _id документов подходящих под фильтры.

Небольшая песочница для Python

Как правило при работе с различными типами данных удобно визуализировать в виде различных иерархических и других табличек.

Это достаточно стандартный функционал для различных ERP решений. И, поскольку часто неизвестно кто будет писать для песочницы код, нужна возможность запускать чужой код более-менее безопасно. На данный момент есть библиотеки, которые дают эту возможность, но точно неизвестно как хорошо они ограничивают запускаемый код.

Пример с eval (для вычисления выражения)

Главное — это:
assert ‘__’ not in src, ‘Prohibited to use symbols «__»‘

тут мы заменяем весь базовый функционал (import, type. ) на нужный/разрешенный функционал.

Источник

Советы мастера