Рубрики
Без рубрики

Агрегации MongoDB С Использованием Java

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

Автор оригинала: 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();

    MongoCollection largestSeven = 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 .