Автор оригинала: Sampada Wagde.
1. Обзор
В этом уроке мы погрузимся в структуру агрегации MongoDB, используя драйвер Java MongoDB .
Сначала мы рассмотрим, что означает агрегирование концептуально, а затем создадим набор данных. Наконец, мы увидим различные методы агрегирования в действии с использованием Агрегатов builder .
2. Что Такое Агрегации?
Агрегации используются в MongoDB для анализа данных и получения из них значимой информации|/.
Они обычно выполняются на различных этапах, и этапы образуют конвейер – таким образом, что выходные данные одного этапа передаются в качестве входных данных на следующий этап.
Наиболее часто используемые этапы можно резюмировать следующим образом:
проект | выбирает только необходимые поля, также может использоваться для вычисления и добавления производных полей в коллекцию | ВЫБИРАТЬ |
совпадение | фильтрует коллекцию в соответствии с указанными критериями | ГДЕ |
группа | собирает входные данные вместе в соответствии с указанными критериями (например, количество, сумма), чтобы вернуть документ для каждой отдельной группы | СГРУППИРОВАТЬ ПО |
сортировать | сортирует результаты в порядке возрастания или убывания данного поля | ЗАКАЗ ПО |
считать | подсчитывает документы, содержащиеся в коллекции | СЧИТАТЬ |
предел | ограничивает результат указанным количеством документов, вместо того чтобы возвращать всю коллекцию | ПРЕДЕЛ |
из | записывает результат в именованную коллекцию; этот этап приемлем только как последний в конвейере | ВЫБЕРИТЕ В НОВОЙ ТАБЛИЦЕ |
То Эквивалент SQL для каждого этапа агрегации приведено выше, чтобы дать нам представление о том, что означает указанная операция в мире SQL.
В ближайшее время мы рассмотрим примеры кода Java для всех этих этапов. Но до этого нам нужна база данных.
3. Настройка базы данных
3.1. Набор данных
Первое и главное требование для изучения всего, что связано с базой данных,-это сам набор данных!
Для целей этого урока мы будем использовать общедоступную конечную точку API restful , которая предоставляет исчерпывающую информацию обо всех странах мира. Этот API предоставляет нам множество точек данных по стране в удобном формате JSON . Некоторые из полей, которые мы будем использовать в нашем анализе, являются:
- название – название страны; например, Соединенные Штаты Америки
- alpha3Code – короткий код для названия страны; например, IND (для Индии)
- регион – регион, к которому относится страна; например, Европа
- площадь – географическая площадь страны
- языки – официальные языки страны в формате массива; например, Английский
- границы – массив кодов соседних стран alpha3/| s
Теперь давайте посмотрим как преобразовать эти данные в коллекцию в базе данных MongoDB .
3.2. Импорт в MongoDB
Во-первых, нам нужно нажать конечную точку API, чтобы получить все страны и сохранить ответ локально в файле JSON . Следующий шаг-импортировать его в MongoDB с помощью команды mongoimport :
mongoimport.exe --db--collection --file --jsonArray
Успешный импорт должен дать нам коллекцию из 250 документов.
4. Примеры агрегирования на Java
Теперь, когда мы рассмотрели базы, давайте перейдем к получению некоторых значимых выводов из имеющихся у нас данных по всем странам . Для этой цели мы будем использовать несколько тестов JUnit.
Но прежде чем мы это сделаем, нам нужно установить соединение с базой данных:
@BeforeClass public static void setUpDB() throws IOException { mongoClient = MongoClients.create(); database = mongoClient.getDatabase(DATABASE); collection = database.getCollection(COLLECTION); }
Во всех следующих примерах мы будем использовать вспомогательный класс Агрегаты , предоставляемый драйвером Java MongoDB .
Для лучшей читабельности наших фрагментов мы можем добавить статический импорт:
import static com.mongodb.client.model.Aggregates.*;
4.1. сопоставление и подсчет
Для начала давайте начнем с чего-нибудь простого. Ранее мы отмечали, что набор данных содержит информацию о языках.
Теперь предположим, что мы хотим проверить количество стран в мире, где английский является официальным языком :
@Test public void givenCountryCollection_whenEnglishSpeakingCountriesCounted_thenNinetyOne() { Document englishSpeakingCountries = collection.aggregate(Arrays.asList( match(Filters.eq("languages.name", "English")), count())).first(); assertEquals(91, englishSpeakingCountries.get("count")); }
Здесь мы используем два этапа в нашем конвейере агрегирования: сопоставление и подсчет .
Во-первых, мы отфильтровываем коллекцию, чтобы она соответствовала только тем документам, которые содержат английский в поле языки|/. Эти документы можно представить как временную или промежуточную коллекцию, которая станет материалом для нашего следующего этапа, count. Это подсчитывает количество документов на предыдущем этапе.
Еще один момент, который следует отметить в этом примере, – это использование метода first . Поскольку мы знаем, что вывод последнего этапа, count , будет одной записью, это гарантированный способ извлечь единственный результирующий документ.
4.2. сгруппировать (с суммой) и отсортировать
В этом примере наша цель состоит в том, чтобы выяснить географический регион, содержащий максимальное количество стран :
@Test public void givenCountryCollection_whenCountedRegionWise_thenMaxInAfrica() { Document maxCountriedRegion = collection.aggregate(Arrays.asList( group("$region", Accumulators.sum("tally", 1)), sort(Sorts.descending("tally")))).first(); assertTrue(maxCountriedRegion.containsValue("Africa")); }
Как очевидно, мы используем группу и сортировку для достижения нашей цели здесь .
Во-первых, мы собираем количество стран в каждом регионе, накапливая сумму их вхождений в переменную подсчет. Это дает нам промежуточный набор документов, каждый из которых содержит два поля: регион и список стран в нем. Затем мы сортируем его в порядке убывания и извлекаем первый документ, чтобы получить регион с максимальным количеством стран.
4.3. сортировка, ограничение и вывод
Теперь давайте используем сортировку , ограничение и выход для извлечения семи крупнейших стран по площади и записи их в новую коллекцию :
@Test public void givenCountryCollection_whenAreaSortedDescending_thenSuccess() { collection.aggregate(Arrays.asList( sort(Sorts.descending("area")), limit(7), out("largest_seven"))).toCollection(); MongoCollectionlargestSeven = database.getCollection("largest_seven"); assertEquals(7, largestSeven.countDocuments()); Document usa = largestSeven.find(Filters.eq("alpha3Code", "USA")).first(); assertNotNull(usa); }
Здесь мы сначала отсортировали данную коллекцию в порядке убывания области. Затем мы использовали метод Aggregates#limit , чтобы ограничить результат только семью документами. Наконец, мы использовали этап out для десериализации этих данных в новую коллекцию под названием largest_seven . Теперь эту коллекцию можно использовать так же, как и любую другую – например, для поиска , если она содержит США.
4.4. проект, группа (с макс.), соответствие
В нашем последнем примере давайте попробуем что-нибудь более хитрое. Скажем, нам нужно выяснить, сколько границ разделяет каждая страна с другими, и каково максимальное такое число .
Теперь в нашем наборе данных у нас есть поле границы , которое представляет собой список массивов alpha3Code s для всех граничащих стран страны, но нет ни одного поля, непосредственно указывающего нам количество. Поэтому нам нужно будет вывести количество граничащих стран использующих проект :
@Test public void givenCountryCollection_whenNeighborsCalculated_thenMaxIsFifteenInChina() { Bson borderingCountriesCollection = project(Projections.fields(Projections.excludeId(), Projections.include("name"), Projections.computed("borderingCountries", Projections.computed("$size", "$borders")))); int maxValue = collection.aggregate(Arrays.asList(borderingCountriesCollection, group(null, Accumulators.max("max", "$borderingCountries")))) .first().getInteger("max"); assertEquals(15, maxValue); Document maxNeighboredCountry = collection.aggregate(Arrays.asList(borderingCountriesCollection, match(Filters.eq("borderingCountries", maxValue)))).first(); assertTrue(maxNeighboredCountry.containsValue("China")); }
После этого, как мы видели ранее, мы сгруппируем прогнозируемую коллекцию, чтобы найти максимальное значение граничащих стран . Здесь следует отметить одну вещь: накопитель max выдает нам максимальное значение в виде числа , а не весь Документ , содержащий максимальное значение. Нам нужно выполнить сопоставление , чтобы отфильтровать нужный Документ , если необходимо выполнить какие-либо дальнейшие операции.
5. Заключение
В этой статье мы рассмотрели что такое агрегации MongoDB и как их применять в Java, используя пример набора данных .
Мы использовали четыре образца для иллюстрации различных этапов агрегирования, чтобы сформировать базовое понимание концепции. Существует множество возможностей для анализа данных, которые предлагает эта платформа, которые можно изучить дополнительно .
Для дальнейшего чтения, Spring Data MongoDB предоставляет альтернативный способ обработки прогнозов и агрегаций в Java.
Как всегда, исходный код доступен на GitHub .