Когда мы начинали изучать MongoDB, наши программисты написали краткий ликбез по основным командам Mongo для своих коллег, чтобы помочь быстро получить представление о ключевых функциях. Наткнувшись недавно на этот пост в недрах нашего корпоративного блога, мы решили, почему бы не поделиться им с широкой общественностью. Надеемся, новичкам пригодится.

MongoDB лого

MongoDB — это документ-ориентированная система управления базами данных (СУБД). Она является одним из наиболее популярных NoSQL решений. Как и следует ожидать, эта база данных (далее БД) легко горизонтально масштабируется, а также имеет свои достоинства и недостатки.

Схема MongoDB сильно отличается от привычной схемы той же MySQL. Базы данных MongoDB состоят из коллекций. Коллекции в свою очередь состоят из документов, а документы —из полей и их значений. Коллекции можно рассматривать как эквивалент таблицам реляционных баз данных.

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

Схема MongoDB

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

Поиск и сортировка

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

db.countries.find();

Это пример того, как запрос выглядит в консоли. Сразу можно увидеть схожесть с объектами из JavaScript. Впрочем, и сама консоль MongoDB написана на JavaScript.

А вот на PHP запрос будет выглядеть по-другому:

$db -> countries -> find();

В последующих примерах мы будем приводить оба варианта: для консоли и для PHP.

Результатом запроса из примера будет список документов, каждый из которых представляет собой JSON-объект:

{
   _id : '549027191cdcaf3594625f4c',
   name: 'Ukraine',
   capital: 'Kiev',
   towns: [
     'Kharkiv', 'Kiev', 'Lviv'
   ],
   population: 45
},
{
   _id : '549027191cdcaf3594625f3c',
   name: 'England',
   capital: 'London',
   towns: [
     'London', 'Liverpool', 'Manchester'
   ],
   population: 53
}

Чтобы отфильтровать результаты запроса по определенным критериям в MongoDB (в SQL это оператор WHERE), мы используем первый аргумент, который передаем функции find():

db.countries.find({name: 'Ukraine'}); (Shell)
$db -> countries -> find(['name' => 'Ukraine']); (PHP)

{
   _id : '549027191cdcaf3594625f4c',
   name: 'Ukraine',
   capital: 'Kiev',
   towns: [
     'Kharkiv', 'Kiev', 'Lviv'
   ],
   population: 45
}

Если необходимо выбрать только определенные поля, передаем функции find() второй аргумент. В SQL мы указываем эти параметры в операторе SELECT.

db.countries.find({name: 'Ukraine'}, {'capital': 1}); (Shell)
$db -> countries -> find(['name' => 'Ukraine'], ['capital' => 1]); (PHP)

{
   _id : '549027191cdcaf3594625f4c',
   capital: 'Kiev'
}

Этот запрос вернет нам значение только одного поля capital из интересующего документа.

Для подсчета количества документов используется функция count();.

db.countries.find({name: 'Ukraine'}, {'capital': 1}).count(); (Shell)
$db -> countries -> find(['name' => 'Ukraine'], ['capital' => 1]) -> count(); (PHP)

Чтобы отсортировать записи по определенным полям, мы используем функцию sort(). Ей передаем объект, по которому будет проходить сортировка.

Направление сортировки задаем числами 1 — сортировка по возрастанию и –1 —  сортировка по убыванию.

db.countries.find().sort({name: 1, capital: -1}); (Shell)
$db -> countries -> find() -> sort(['name' => 1, 'capital' => -1]) (PHP)

В приведенных запросах сортировка сначала идет по полю name по возрастанию, а затем по полю capital по убыванию.

В MongoDB есть ряд специальных операторов $lt, $lte, $gt, $gte и $ne. Они используются для выражения операций «меньше», «меньше или равно», «больше», «больше или равно» и «не равно».

db.countries.find({population: {$gt: 50}}); (Shell)
$db -> countries -> find(['population' => ['$gt' => 50]]) (PHP)

Данный запрос выбирает страны с населением больше 50 млн.

Также есть оператор $or (ИЛИ)

db.countries.find({$or: [{towns: 'Kharkiv'}, {towns: 'London'}]}); (Shell)
$db -> countries -> find(['$or' => [['towns' => 'Kharkiv'], ['towns' => 'London']]]); (PHP)

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

Вставка, изменение, обновление

Если нам нужно удалить записи, мы используем функцию remove(), которой, как и функции find(), передаем объект настроек:

db.countries.remove({capital: 'London'}); (Shell)
$db -> countries -> remove(['capital' => 'London']); (PHP)

Стоит заметить, если для функции remove() не указать ни одного параметра, то будут удалены все записи из базы данных.

Для добавления новых записей в базу применим функцию insert();

db.countries.insert({name: 'USA', capital: 'Washington', towns: ['New York', 'Washington'], population: 322}); (Shell)
$db -> countries -> insert(['name' => 'USA', 'capital' => 'Washington', towns: ['New York', 'Washington'], 'population' => 322]); (PHP)

Чтобы обновить или изменить записи используем функцию update, которая слегка отличается от UPDATE в SQL. Функция принимает два аргумента-объекта: первый указывает, в какие документы в коллекции следует внести изменения, а второй показывает, какие именно изменения необходимо внести. Стоит заметить, что без оператора $set существующий документ будет заменен на документ с полями, указанными во втором параметре.

db.countries.update({name: 'Ukraine'}, {$set: {population: 50}}); (Shell)
$db -> countries -> update(['name' => 'Ukraine'], ['$set' => ['population' => 50]]); (PHP)

Запрос из примера обновит количество населения в Украине.

У этой функции есть еще два полезных аргумента: upsert и multi.

Upsert разрешает создать новый документ, соответствующий указанным критериям, если его не существует в базе. Multi разрешает множественное обновление документов.

db.countries.update({}, {$set: {population: 50}}, false, true); (Shell)
$db -> countries -> update([], ['$set' => ['population' => 50]], ['upsert' => false, 'multi' => true]); (PHP)

Также у функции update() есть оператор $inc, который увеличивает/уменьшает значение поля на заданную величину и оператор $push, который добавляет значение в массив.

db.countries.update({}, {$inc: {population: 2}}, false, true); (Shell)
$db -> countries -> update([], ['$inc' => ['population' => 2]], ['upsert' => false, 'multi' => true]); (PHP)

Этот запрос увеличивает количество населения у всех стран на 2 млн.

db.countries.update({name: 'Ukraine'}, {$push: {towns: 'Mariupol'}}); (Shell)
$db -> countries -> update(['name' => 'Ukraine'], ['$push' => ['towns' => 'Mariupol']]); (PHP)

А этот запрос добавит Мариуполь в массив городов Украины.

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

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

Примеры использования MongoDB

В качестве примера использования MongoDB можно упомянуть Yandex Диск. Они используют эту СУБД для хранения метаданных, и на ноябрь 2014 на шардах хранилось 12 млрд. объектов, объемом 12 ТБ (5 ТБ занимали индексы). А количество запросов в день превышало 6 млрд. Но, как сами заявили, они чувствуют себя не очень комфортно с этой базой данных, поскольку сделали неверные архитектурные решения при проектировании.

Как видим, самое главное — это правильно организовать данные и применять Mongo только там, где ее действительно можно применить. Сама собой MongoDB, конечно же, не претендует на полноценную замену привычных реляционных СУБД, таких как MySQL или PostgreSQL. Однако ее можно использовать для увеличения быстродействия отдельных элементов архитектуры в комплексе с другими БД. Неплохим решением будет применение MongoDB для ведения статистики, системы кэширования, хранения пользовательских сессий, ведения системного журнала и т.п.

Например, мы используем эту СУБД в комплексе с другими технологиями в одном из наших проектов в двух случаях:

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

Проект пока не тестировался под нагрузкой. Однако мы ожидаем, что прирост по скорости обмена данными будет более значительным по сравнению с MySQL. В качестве основной СУБД для этого проекта мы используем MariaDB, а серверный код написан на PHP с использованием JavaScript, Node.js.

 

***

Надеемся наша статья была для вас полезной. Если вы хотите использовать MongoDB в своих проектах, но еще не определились, где и как ее можно применить — пишите нам. Мы рады вам помочь!

Запись опубликована в рубрике screen.ua.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>