MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Agrégations MongoDB utilisant Java

1. Présentation

Dans ce didacticiel, nous allons plonger dans le cadre d'agrégation MongoDB à l'aide du pilote Java MongoDB .

Nous allons d'abord examiner ce que signifie l'agrégation sur le plan conceptuel, puis configurer un ensemble de données. Enfin, nous verrons diverses techniques d'agrégation en action à l'aide du générateur d'agrégats .

2. Que sont les agrégations ?

Les agrégations sont utilisées dans MongoDB pour analyser les données et en tirer des informations significatives .

Ceux-ci sont généralement exécutés en différentes étapes, et les étapes forment un pipeline - de sorte que la sortie d'une étape est transmise comme entrée à l'étape suivante.

Les étapes les plus couramment utilisées peuvent être résumées comme suit :

Étape Équivalent SQL Description
 projet SELECT sélectionne uniquement les champs obligatoires, peut également être utilisé pour calculer et ajouter des champs dérivés à la collection
 correspondance filtre la collection selon les critères spécifiés
 groupe GROUPER PAR rassemble les entrées selon les critères spécifiés (par exemple, nombre, somme) pour renvoyer un document pour chaque groupement distinct
 trier ORDER BY trie les résultats par ordre croissant ou décroissant d'un champ donné
 compter COUNT compte les documents contenus dans la collection
 limite LIMIT limite le résultat à un nombre spécifié de documents, au lieu de renvoyer la collection entière
 out SELECT INTO NEW_TABLE écrit le résultat dans une collection nommée ; cette étape n'est acceptable que comme la dernière d'un pipeline


L'équivalent SQL pour chaque étape d'agrégation est inclus ci-dessus pour nous donner une idée de ce que signifie ladite opération dans le monde SQL.

Nous examinerons bientôt des exemples de code Java pour toutes ces étapes. Mais avant cela, nous avons besoin d'une base de données.

3. Configuration de la base de données

3.1. Ensemble de données

La première et principale exigence pour apprendre tout ce qui concerne les bases de données est l'ensemble de données lui-même !

Pour les besoins de ce didacticiel, nous utiliserons un point de terminaison d'API reposant accessible au public qui fournit des informations complètes sur tous les pays du monde. Cette API nous donne beaucoup de points de données pour un pays dans un format JSON pratique . Certains des champs que nous utiliserons dans notre analyse sont :

  • nom – le nom du pays; par exemple, États-Unis d'Amérique
  • code alpha3 – un shortcode pour le nom du pays; par exemple, IND (pour l'Inde)
  • région – la région à laquelle appartient le pays; par exemple, Europe
  • zone – la zone géographique du pays
  • langues – langues officielles du pays sous forme de tableau; par exemple, Anglais
  • bordures – un tableau de alpha3Code des pays voisins s

Voyons maintenant comment convertir ces données en une collection dans une base de données MongoDB .

3.2. Importation vers MongoDB

Tout d'abord, nous devons atteindre le point de terminaison de l'API pour obtenir tous les pays et enregistrer la réponse localement dans un fichier JSON . L'étape suivante consiste à l'importer dans MongoDB à l'aide de mongoimport commande :

mongoimport.exe --db <db_name> --collection <collection_name> --file <path_to_file> --jsonArray

Une importation réussie devrait nous donner une collection de 250 documents.

4. Exemples d'agrégation en Java

Maintenant que nous avons couvert les bases, passons à dériver des informations significatives à partir des données dont nous disposons pour tous les pays . Nous utiliserons plusieurs tests JUnit à cette fin.

Mais avant cela, nous devons établir une connexion à la base de données :

@BeforeClass
public static void setUpDB() throws IOException {
    mongoClient = MongoClients.create();
    database = mongoClient.getDatabase(DATABASE);
    collection = database.getCollection(COLLECTION);
}

Dans tous les exemples qui suivent, nous utiliserons les agrégats classe d'assistance fournie par le pilote Java MongoDB.

Pour une meilleure lisibilité de nos extraits, nous pouvons ajouter un import statique :

import static com.mongodb.client.model.Aggregates.*;

4.1. correspondre et compter

Pour commencer, commençons par quelque chose de simple. Nous avons noté précédemment que l'ensemble de données contient des informations sur les langues.

Maintenant, disons que nous voulons vérifier le nombre de pays dans le monde où l'anglais est une langue officielle :

@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"));
}

Nous utilisons ici deux étapes dans notre pipeline d'agrégation :correspondance et compter .

Tout d'abord, nous filtrons la collection pour faire correspondre uniquement les documents qui contiennent Anglais dans leur langue domaine. Ces documents peuvent être imaginés comme une collection temporaire ou intermédiaire qui devient l'intrant de notre prochaine étape, comptage. Cela compte le nombre de documents à l'étape précédente.

Un autre point à noter dans cet exemple est l'utilisation de la méthode première . Puisque nous savons que la sortie de la dernière étape, compter , va être un seul enregistrement, c'est un moyen garanti d'extraire le seul document résultant.

4.2. groupe (avec somme ) et trier

Dans cet exemple, notre objectif est de connaître la zone géographique contenant le nombre maximum de pays :

@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"));
}

Comme il est évident, nous utilisons group et trier pour atteindre notre objectif ici .

Tout d'abord, nous rassemblons le nombre de pays dans chaque région en accumulant une somme de leurs occurrences dans une variable tally. Cela nous donne une collection intermédiaire de documents, contenant chacun deux champs :la région et le décompte des pays qui la composent. Ensuite, nous le trions dans l'ordre décroissant et extrayons le premier document pour nous donner la région avec le maximum de pays.

4.3. trier, limite, et dehors

Utilisons maintenant trier , limite et dehors pour extraire les sept plus grands pays par zone et les écrire dans une nouvelle collection :

@Test
public void givenCountryCollection_whenAreaSortedDescending_thenSuccess() {
    collection.aggregate(Arrays.asList(
      sort(Sorts.descending("area")), 
      limit(7),
      out("largest_seven"))).toCollection();

    MongoCollection<Document> largestSeven = database.getCollection("largest_seven");

    assertEquals(7, largestSeven.countDocuments());

    Document usa = largestSeven.find(Filters.eq("alpha3Code", "USA")).first();

    assertNotNull(usa);
}

Ici, nous avons d'abord trié la collection donnée dans l'ordre décroissant de zone. Ensuite, nous avons utilisé les Aggregates#limit méthode pour restreindre le résultat à sept documents seulement. Enfin, nous avons utilisé le out étape pour désérialiser ces données dans une nouvelle collection appelée largest_seven . Cette collection peut maintenant être utilisée de la même manière que n'importe quelle autre - par exemple, pour trouver s'il contient USA.

4.4. projet, groupe (avec max), correspondance

Dans notre dernier exemple, essayons quelque chose de plus délicat. Disons que nous devons découvrir combien de frontières chaque pays partage avec d'autres, et quel est le nombre maximum .

Maintenant, dans notre jeu de données, nous avons un borders champ, qui est un tableau listant alpha3Code s pour tous les pays limitrophes de la nation, mais il n'y a pas de champ nous donnant directement le compte. Nous devrons donc dériver le nombre de borderingCountries en utilisant projet :

@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"));
}

Après cela, comme nous l'avons vu précédemment, nous allons regrouper la collection projetée pour trouver le max valeur de borderingCountries . Une chose à souligner ici est que le max l'accumulateur nous donne la valeur maximale sous forme de nombre , et non l'intégralité du Document contenant la valeur maximale. Nous devons effectuer une correspondance pour filtrer le Document souhaité si d'autres opérations doivent être effectuées.