MongoDB-aggregaties met behulp van Java

1. Overzicht

In deze tutorial nemen we een duik in het MongoDB Aggregation-framework met behulp van het MongoDB Java-stuurprogramma.

We zullen eerst kijken naar wat aggregatie conceptueel betekent, en vervolgens een dataset opzetten. Eindelijk zullen we zien verschillende aggregatietechnieken in actie met behulp van Aggregates builder.

2. Wat zijn aggregaties?

Aggregaties worden in MongoDB gebruikt om gegevens te analyseren en er zinvolle informatie uit te halen.

Deze worden meestal in verschillende fasen uitgevoerd en de fasen vormen een pijplijn - zodanig dat de output van de ene fase wordt doorgegeven als input naar de volgende fase.

De meest gebruikte fasen kunnen worden samengevat als:

StadiumSQL-equivalentOmschrijving
projectSELECTEERselecteert alleen de vereiste velden, kan ook worden gebruikt om te berekenen en afgeleide velden aan de verzameling toe te voegen
bij elkaar passenWAARfiltert de collectie volgens gespecificeerde criteria
groepGROEP OPverzamelt invoer volgens de gespecificeerde criteria (bijv. aantal, som) om een ​​document te retourneren voor elke afzonderlijke groepering
soortBESTEL DOORsorteert de resultaten in oplopende of aflopende volgorde van een bepaald veld
tellenAANTALtelt de documenten die de collectie bevat
limietLIMIETbeperkt het resultaat tot een bepaald aantal documenten, in plaats van de hele collectie terug te sturen
uitSELECTEER IN NEW_TABLEschrijft het resultaat naar een benoemde verzameling; deze fase is alleen acceptabel als de laatste in een pijplijn

Het SQL-equivalent voor elke aggregatiefase is hierboven opgenomen om ons een idee te geven van wat de genoemde bewerking betekent in de SQL-wereld.

We zullen binnenkort naar Java-codevoorbeelden voor al deze fasen kijken. Maar daarvoor hebben we een database nodig.

3. Database-instellingen

3.1. Dataset

De eerste en belangrijkste vereiste om iets databasegerelateerd te leren, is de dataset zelf!

Voor deze tutorial gebruiken we een openbaar beschikbaar rustgevend API-eindpunt dat uitgebreide informatie biedt over alle landen van de wereld. Deze API geeft ons veel datapunten voor een land in een handig JSON-formaat. Enkele van de velden die we in onze analyse zullen gebruiken, zijn:

  • naam - de naam van het land; bijvoorbeeld, Verenigde Staten van Amerika
  • alpha3Code - een shortcode voor de naam van het land; bijvoorbeeld, IND (voor India)

  • regio - de regio waartoe het land behoort; bijvoorbeeld, Europa
  • Oppervlakte - het geografische gebied van het land
  • talen - officiële talen van het land in een array-indeling; bijvoorbeeld, Engels
  • grenzen - een scala aan buurlanden ' alpha3Codes

Laten we nu eens kijken hoe u deze gegevens omzet in een verzameling in een MongoDB-database.

3.2. Importeren naar MongoDB

Ten eerste moeten we raak het API-eindpunt om alle landen op te halen en sla het antwoord lokaal op in een JSON-bestand. De volgende stap is om het in MongoDB te importeren met behulp van de mongoimport opdracht:

mongoimport.exe --db --collection --file --jsonArray

Een succesvolle import zou ons een collectie met 250 documenten moeten opleveren.

4. Aggregatiemonsters in Java

Nu we de bases hebben gedekt, laten we ingaan enkele zinvolle inzichten afleiden uit de gegevens die we hebben voor alle landen. We zullen hiervoor verschillende JUnit-tests gebruiken.

Maar voordat we dat doen, moeten we verbinding maken met de database:

@BeforeClass openbare statische leegte setUpDB () gooit IOException {mongoClient = MongoClients.create (); database = mongoClient.getDatabase (DATABASE); collection = database.getCollection (COLLECTION); } 

In alle voorbeelden die volgen, we zullen de Aggregaten helper-klasse die wordt geleverd door het MongoDB Java-stuurprogramma.

Voor een betere leesbaarheid van onze fragmenten kunnen we een statische import toevoegen:

importeer statische com.mongodb.client.model.Aggregates. *;

4.1. bij elkaar passen en tellen

Laten we om te beginnen beginnen met iets eenvoudigs. Eerder merkten we op dat de dataset informatie over talen bevat.

Laten we nu zeggen dat we het willen controleer het aantal landen in de wereld waar Engels een officiële taal is:

@Test openbare ongeldig gegevenCountryCollection_whenEnglishSpeakingCountriesCounted_thenNinetyOne () {Document englishSpeakingCountries = collection.aggregate (Arrays.asList (match (Filters.eq ("languages.name", "Engels")), count ())). First (); assertEquals (91, englishSpeakingCountries.get ("count")); }

Hier gebruiken we twee fasen in onze aggregatiepijplijn: bij elkaar passen en tellen.

Ten eerste filteren we de verzameling uit zodat deze alleen overeenkomt met de documenten die Engels in hun talen veld. Deze documenten kunnen worden voorgesteld als een tijdelijke of tussentijdse verzameling die de input wordt voor onze volgende fase, tellen. Dit telt het aantal documenten in de vorige fase.

Een ander punt om op te merken in dit voorbeeld is het gebruik van de methode eerste. Omdat we weten dat de output van de laatste fase, tellen, wordt een enkel record, dit is een gegarandeerde manier om het enige resulterende document eruit te halen.

4.2. groep (met som) en soort

In dit voorbeeld is ons doel om ontdek de geografische regio met het maximale aantal landen:

@Test openbare leegte gegevenCountryCollection_whenCountedRegionWise_thenMaxInAfrica () {Document maxCountriedRegion = collection.aggregate (Arrays.asList (group ("$ region", Accumulators.sum ("tally", 1)), sort (Sorts.descending) ("tally")) ).eerste(); assertTrue (maxCountriedRegion.containsValue ("Afrika")); }

Zoals duidelijk is, wij gebruiken groep en soort om ons doel hier te bereiken.

Eerst verzamelen we het aantal landen in elke regio door een som van hun voorkomen in een variabele tally. Dit geeft ons een tussenverzameling van documenten, elk met twee velden: de regio en het aantal landen erin. Vervolgens sorteren we het in aflopende volgorde en extraheren we het eerste document om ons de regio met het maximum aantal landen te geven.

4.3. soort,limiet, en uit

Laten we nu gebruiken soort, limiet en uit om de zeven grootste landen per gebied te extraheren en ze in een nieuwe verzameling te schrijven:

@Test openbare leegte gegevenCountryCollection_whenAreaSortedDescending_thenSuccess () {collection.aggregate (Arrays.asList (sort (Sorts.descending ("area")), limit (7), out ("grootste_zeven"))). ToCollection (); MongoCollection grootsteSeven = database.getCollection ("grootste_zeven"); assertEquals (7, grootsteSeven.countDocuments ()); Document usa = grootsteSeven.find (Filters.eq ("alpha3Code", "VS")). First (); assertNotNull (usa); }

Hier hebben we eerst de gegeven verzameling gesorteerd in aflopende volgorde van Oppervlakte. Vervolgens hebben we de Aggregaten # limiet methode om het resultaat te beperken tot slechts zeven documenten. Ten slotte hebben we de uit fase om deze gegevens te deserialiseren naar een nieuwe verzameling met de naam grootste_zeven. Deze collectie kan nu op dezelfde manier worden gebruikt als alle andere, bijvoorbeeld om vind als het bevat VS.

4.4. project, groep (met max), match

Laten we in ons laatste voorbeeld iets moeilijkers proberen. Zeg dat we het moeten doen ontdek hoeveel grenzen elk land met anderen deelt, en wat het maximale aantal is.

Nu hebben we in onze dataset een grenzen veld, wat een array-lijst is alpha3Codes voor alle aangrenzende landen van de natie, maar er is geen enkel veld dat ons rechtstreeks de telling geeft. Dus we moeten het aantal afleiden aangrenzende landen gebruik makend van project:

@Test openbare leegte gegevenCountryCollection_whenNeighurenCalculated_thenMaxIsFifteenInChina () {Bson borderingCountriesCollection = project (Projections.fields (Projections.excludeId (), Projections.include ("name"), Projections.computed ("borderingCountries,", Projections.com "," $ borders ")))); int maxValue = collection.aggregate (Arrays.asList (borderingCountriesCollection, group (null, Accumulators.max ("max", "$ borderingCountries")))) .first (). getInteger ("max"); assertEquals (15, maxValue); Document maxNe NeighboredCountry = collection.aggregate (Arrays.asList (borderingCountriesCollection, match (Filters.eq ("borderingCountries", maxValue)))). First (); assertTrue (maxNe NeighboredCountry.containsValue ("China")); }

Daarna, zoals we eerder zagen, zullen we groep de geprojecteerde collectie om de max. hoogte waarde van aangrenzende landen. Een ding om hier op te wijzen is dat de max. hoogte accumulator geeft ons de maximale waarde als getal, niet het hele Document met de maximale waarde. We moeten presteren bij elkaar passen om het gewenste uit te filteren Document als er nog meer bewerkingen moeten worden uitgevoerd.

5. Conclusie

In dit artikel hebben we gezien wat zijn MongoDB-aggregaties en hoe ze in Java kunnen worden toegepast met behulp van een voorbeelddataset.

We hebben vier voorbeelden gebruikt om de verschillende aggregatiefasen te illustreren om een ​​basisbegrip van het concept te krijgen. Dit framework biedt talloze mogelijkheden voor data-analyse die verder kunnen worden onderzocht.

Voor meer informatie biedt Spring Data MongoDB een alternatieve manier om projecties en aggregaties in Java af te handelen.

Zoals altijd is de broncode beschikbaar op GitHub.