Статьи

MongoDB Учебник для начинающих

1. Введение в MongoDB

В этой статье мы расскажем о всеобъемлющем руководстве по MongoDB, которое интегрируется с Java-приложением. Всякий раз, когда мы читаем о базах данных NoSQL, мы должны знать, почему они когда-либо разрабатывались, когда базы данных SQL работали отлично. Основы NoSQL выросли на основе упрощенных ACID (атомарность, согласованность, изоляция, долговечность) в пользу производительности, масштабируемости, гибкости и снижения сложности. Большинство баз данных NoSQL пошли тем или иным способом, предоставляя как можно больше ранее упомянутых качеств, даже предлагая разработчикам настраиваемые гарантии.

MongoDB — это кросс-платформенная база данных с открытым исходным кодом, ориентированная на документы и разработанная на C ++, которая является одной из самых популярных и используемых баз данных типа NoSQL. Он работает поверх JSON-подобных документов с парами ключ-значение, схема которых может оставаться неопределенной в каждом документе. Кроме того, его можно использовать бесплатно, так как он публикуется под сочетанием Стандартной общественной лицензии GNU Affero и Лицензии Apache. MongoDB хранит данные в JSON-подобных документах (называемых BSON), которые могут иметь динамическую схему для документов в одной коллекции. Структуру документа в той же коллекции можно изменить, просто добавив новые поля или удалив существующие.

В этой статье мы рассмотрим некоторые характеристики этой базы данных NoSQL и ее развитие в различных версиях, добавив новые функции с улучшенной масштабируемостью и производительностью. Мы также разработаем небольшой Java-проект на основе Maven, в котором мы выполним некоторые примеры запросов с драйвером MongoDB для Java .

2. Развитие MongoDB

MongoDB был разработан 10gen и впервые выпущен 27 августа 2009 года. Первая версия MongoDB была выпущена с некоторыми базовыми функциями, авторизацией и гарантиями ACID, что компенсировало недостатки с точки зрения производительности и гибкости. Опять же, некоторые основные функции для v1.0 и v1.2 были:

  • Модель документа на основе JSON
  • Глобальная блокировка на уровне процесса
  • Индексы на коллекциях, которые находятся в оперативной памяти (в основном)
  • CRUD операции с документами в коллекции
  • Поддержка репликации в архитектуре Master Slave
  • Map-Reduce (поддерживается в версии 1.2)
  • Функции Javascript (поддерживаются в v1.2)

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

  • Sharding (поддерживается в v1.6)
  • Операторы запросов (поддерживаются в v1.6)
  • Разреженные и покрытые индексы (поддерживается в v1.8)
  • Гораздо более эффективное использование памяти
  • Улучшения параллелизма
  • Улучшения MapReduce
  • Аутентификация (поддерживается в v2.0 для Sharding)
  • Геопространственный запрос и поддержка данных

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

  • Структура агрегации (поддерживается в v2.2)
  • Поиск текста (поддерживается в v2.4)
  • Хешированные индексы (поддерживается в v2.4)
  • Улучшения безопасности, ролевый доступ к базам данных (поддерживается в v2.4)
  • Движок V8 JavaScript (заменяет SpiderMonkey, начиная с v2.4)
  • Улучшения движка запросов (начиная с версии 2.6)
  • Проверка документов (начиная с версии 3.2)
  • Несколько механизмов хранения (начиная с версии 3.2, только для редакции Enterprise)

Когда мы начинаем замечать возможности, которые MongoDB добавлял с тех пор, как он начал развиваться, мы можем легко увидеть, что в своем текущем состоянии MongoDB представляет собой базу данных, которая может обрабатывать множество данных, начиная от загрузочных MVP и POC до корпоративных приложений с сотнями серверов. и более.

3. Терминология MongoDB для разработчиков SQL

Мы можем понять концепции MongoDB намного быстрее, если проведем сравнение терминологии SQL и концепций NoSQL. Вот простое сравнение по аналогии между Mongo и традиционной системой MySQL:

  • Таблицы в MySQL становятся коллекциями в MongoDB
  • Строка становится документом
  • Колонна становится полем
  • Объединения определяются как ссылки и встроенные документы (подробнее об этом позже)

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

4. Создание проекта Java с Maven

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

Создание проекта

1
mvn archetype:generate -DgroupId=com.javacodegeeks.example -DartifactId=JCG-JavaMongoDB-Example -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Если вы запускаете maven в первый раз, выполнение команды генерации займет несколько секунд, поскольку maven должен загрузить все необходимые плагины и артефакты, чтобы выполнить задачу генерации. Как только мы запустим этот проект, мы увидим следующий результат и проект будет создан:

MongoDB Tutorial - Настройка проекта

Настройка Java MongoDB Project

5. Добавление зависимостей Maven

Создав проект, не стесняйтесь открывать его в своей любимой среде IDE. Следующим шагом является добавление соответствующих зависимостей Maven в проект. Мы будем работать со следующими зависимостями в нашем проекте:

  • mongo-java-driver : эта зависимость mongo-java-driver MongoDB для Java в наши зависимости.

Вот файл pom.xml с добавленными соответствующими зависимостями:

pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.javacodegeeks.example</groupId>
    <artifactId>JCG-JavaMongoDB-Example</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>JCG-JavaMongoDB-Example</name>
    <url>http://maven.apache.org</url>
 
    <dependencies>
 
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.4.1</version>
        </dependency>
 
    </dependencies>
 
</project>

Если вы хотите проверить и использовать более новую версию для драйвера, проверьте выпуски здесь .

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

Проверьте дерево зависимостей

1
mvn dependency:tree

Когда мы запустим эту команду, она покажет нам следующее дерево зависимостей:

MongoDB Tutorial - Проверка дерева зависимостей

Проверьте дерево зависимостей

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

6. Структура проекта

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

MongoDB Tutorial - Структура проекта

Структура проекта

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

7. Использование MongoDB с Java

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

7.1 Установление соединения с MongoDB

Первым шагом для работы с базой данных в любом приложении является подключение к ней. Мы можем подключиться к MongoDB путем аутентификации в authentication-database (по умолчанию admin ) следующим образом:

MongoApp.java

1
2
3
4
5
6
7
8
System.out.println("Connecting to DB...");
List<MongoCredential> credentialsList = new ArrayList<>();
//Use username, authtication database and password in MongoCredential object
MongoCredential creds = MongoCredential.createCredential("db_user", "admin", "db_password".toCharArray());
credentialsList.add(creds);
ServerAddress serverAddress = new ServerAddress("localhost", 27017); //host and port
MongoClient mongoClient = new MongoClient(serverAddress, credentialsList);
System.out.println("Connected to MongoDB...");

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

MongoApp.java

1
MongoClient mongoClient = new MongoClient("localhost", 27017);

Теперь мы готовы запускать различные команды с этим объектом MongoClient который установил и сохранил в нем соединение с БД.

7.2 Показать существующие базы данных

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

Показать базы данных с оболочкой Mongo

1
show databases;

Эту же операцию можно выполнить и со следующим фрагментом кода Java:

Показать базы данных с Java

1
2
// print existing databases
mongoClient.getDatabaseNames().forEach(System.out::println);

Это покажет существующие базы данных в системе:

Выход

1
2
admin
local

В приведенном выше выводе local является базой данных Mongo по умолчанию.

7.3 Создать коллекцию

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

MongoApp.java

1
2
3
4
5
6
// get database
MongoDatabase jcgDatabase = mongoClient.getDatabase("JavaCodeGeeks");
 
// create collection
jcgDatabase.createCollection("authors");
jcgDatabase.createCollection("posts");

Следует отметить, что мы никогда не создавали упомянутую базу данных . Тем не менее, MongoDB не будет выдавать никаких ошибок. Он оптимистичен и понимает, что если БД не существует, он создаст ее для вас. Если вы снова запустите команду show database, на этот раз мы увидим другой результат:

Базы данных

1
2
3
JavaCodeGeeks
admin
local

База данных была создана автоматически.

7.4 Сохранить — вставить в коллекцию

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

вставка

1
2
3
4
5
6
7
MongoCollection<Document> authorCollection = jcgDatabase.getCollection("authors");
Document document = new Document();
document.put("name", "Shubham");
document.put("company", "JCG");
document.put("post_count", 20);
authorCollection.insertOne(document);
System.out.println("Inserted document = " + document);

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

Выход

1
Inserted document = Document{{name=Shubham, company=JCG, post_count=20, _id=5b77c15cf0406c64b6c9dae4}}

7.5 Сохранить — обновить существующий документ

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

Обновление документа

01
02
03
04
05
06
07
08
09
10
11
12
13
14
//Find existing document
Document updateQuery = new Document();
updateQuery.put("name", "Shubham");
 
//Field to update
Document newNameDocument = new Document();
newNameDocument.put("name", "Shubham Aggarwal");
 
//Perform set operation
Document updateObject = new Document();
updateObject.put("$set", newNameDocument);
 
UpdateResult updateResult = authorCollection.updateOne(updateQuery, updateObject);
System.out.println("Documents updated: " + updateResult.getModifiedCount());

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

Выход

1
Documents updated: 1

Как мы заметили, в этом предоставленном фрагменте кода save следовал соглашению об обновлении, потому что мы использовали объект с заданным _id .

7.6 Получение всех документов в коллекции

Легко найти все документы, присутствующие в коллекции, для которой нам просто нужно предоставить объект запроса, по которому выполняется фильтрация, прежде чем документы будут извлечены из коллекций. Давайте посмотрим, как это можно сделать с помощью фрагмента кода Java:

Получить все документы

1
2
3
4
5
6
7
8
Document searchQuery = new Document();
searchQuery.put("company", "JCG");
 
FindIterable<Document> documents = authorCollection.find(searchQuery);
 
for (Document document: documents) {
    System.out.println(document);
}

Мы получим следующий вывод, как только запустим приведенный выше код:

Выход

1
Document{{_id=5b77c15cf0406c64b6c9dae4, name=Shubham Aggarwal, company=JCG, post_count=20}}

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

7.7 Удаление документа

Удалить документ легко. Нам просто нужно предоставить фильтр запроса, и работа будет выполнена.

pom.xml

1
2
3
4
Document deleteSearchQuery = new Document();
deleteSearchQuery.put("_id", new ObjectId("5b77c15cf0406c64b6c9dae4"));
DeleteResult deleteResult = authorCollection.deleteOne(deleteSearchQuery);
System.out.println("Documents updated: " + deleteResult.getDeletedCount());

Мы получим следующий вывод, как только запустим приведенный выше код:

Выход

1
Documents updated: 1

Обратите внимание, что мы использовали значение ID не как String а как ObjectId потому что это то, что понимает MongoDB. Хотя вполне возможно использовать простую строку в качестве идентификатора, но другие типы не поддерживаются для полей идентификации. Наконец, обратите внимание, что мы использовали метод deleteOne который удаляет только один документ. Даже если MongoDB находит более одного документа для предоставленного фильтра (в случае идентификатора он не может найти более одного, но возможно в других случаях), он все равно удалил бы из них только один документ (удаляется первый соответствующий документ). Чтобы удалить все отфильтрованные документы, мы можем использовать метод deleteMany .

8. Поле _id Decoded

Каждый документ MongoDB имеет поле _id которое является уникальным идентификатором для данного документа в коллекции. Это выглядит примерно так:

_мне бы

1
2
3
4
{
    "_id" : ObjectId("5b77c15cf0406c64b6c9dae4")
    ... other fields ...
}

Часто люди (определенно не разработчики) думают, что это случайно сгенерированный токен String, который тщательно выбирается, чтобы он оставался уникальным для любого числа документов, сохраненных в этой коллекции. Но это не так. Каждый _id всех документов в MongoDB представляет собой 12-байтовое шестнадцатеричное число, гарантирующее уникальность документа в коллекции. Он генерируется MongoDB, если не предоставлен самим разработчиком (в этом случае значение этой строки полностью изменится, но все равно останется уникальным идентификатором в коллекции).

Из 12 байтов начальные 4 байта отображают текущую временную метку, следующие 3 байта представляют идентификатор машины, следующие 2 байта описывают идентификатор процесса для сервера MongoDB на этом компьютере, а последние 3 байта являются простым счетчиком автоинкремента. поддерживается сервером MongoDB. Это также можно объяснить простой диаграммой:

MongoDB Tutorial - _id поле декодируется

_id поле декодировано

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

9. Ограничения MongoDB

Хотя MongoDB может масштабироваться и имеет сверхбыстрые индексы, у него также есть некоторые возможные недостатки. Мы использовали термин «возможно», так как это может или не может быть недостатком для вашего варианта использования. Давайте посмотрим на некоторые из этих недостатков здесь:

  • Максимальный размер, который может занимать каждый документ, составляет 16 МБ.
  • Максимальный уровень вложенности документа в документе MongoDB составляет 100
  • Имя базы данных ограничено 64 символами
  • Если мы применяем индекс к любому полю, значение этого поля не может содержать более 1024 байтов.
  • Хешированный индекс не может быть уникальным
  • Вы не можете выполнить откат автоматически, если объем данных превышает 300 МБ. В таких случаях необходимо ручное вмешательство

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

10. MongoDB против RDBMS

Битва баз данных MongoDB и RDBMS никогда не заканчивается. Разработчики всегда ведут длительную дискуссию о том, какой из них быстрее или лучше другого, но ответ таков: нет никакого сравнения между этими двумя из-за вариантов использования, при которых каждый из них используется. Чтобы упомянуть, давайте опишем преимущества MongoDB над базами данных RDBS здесь:

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

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

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

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

11. Заключение

На этом уроке мы быстро познакомились с использованием MongoDB в простом Java-приложении на основе maven и выполнили операции CRUD в наших коллекциях с обновленным API.

Мы также изучили различные преимущества MongoDB. Хотя может быть много вариантов использования, в которых вы захотите использовать MongoDB поверх базы данных SQL, я думаю, что гибкость схемы, скорее всего, является наиболее важным фактором, влияющим на это решение. MongoDB предоставляет нам возможность хранить данные или документы в коллекции, которая может иметь различные поля, которые могут очень помочь на этапе разработки приложения, а также при приеме данных из нескольких источников, которые могут иметь или не иметь одинаковые свойства и схему связан с ними. По сравнению с базой данных RDBMS, где столбцы должны быть предварительно определены и иметь разреженные данные, могут быть оштрафованы, в MongoDB это норма, и это особенность, которую разделяют большинство вариантов использования. Возможность глубоко вкладывать атрибуты в документы, добавлять массивы значений в атрибуты, и в то же время возможность поиска и индексации этих полей помогает разработчикам приложений использовать бессхемную природу MongoDB.

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

12. Загрузите исходный код

Это был учебник MongoDB с языком программирования Java.

Скачать
Вы можете скачать полный исходный код этого примера здесь: Пример MongoDB