Spring Data MongoDB: Projections and Aggregations

1. Oversigt

Spring Data MongoDB giver enkle abstraktioner på højt niveau til det native MongoDB-forespørgselssprog. I denne artikel vi vil undersøge støtten til rammerne for fremskrivninger og sammenlægning.

Hvis du er ny på dette emne, henvises til vores introduktionsartikel Introduktion til Spring Data MongoDB.

2. Fremskrivning

I MongoDB er fremskrivninger en måde at kun hente de krævede felter i et dokument fra en database. Dette reducerer mængden af ​​data, der skal overføres fra databaseserver til klient, og øger dermed ydeevnen.

Med Spring Data MongDB kan fremskrivninger bruges begge med MongoTemplate og MongoRepository.

Før vi går videre, lad os se på den datamodel, vi vil bruge:

@Document offentlig klasse bruger {@Id privat streng-id; privat strengnavn; privat heltalealder // standard getters og setter}

2.1. Fremskrivninger ved hjælp af MongoTemplate

Det omfatte() og udelukke() metoder til Mark klasse bruges til at inkludere og ekskludere felter henholdsvis:

Forespørgsel = ny forespørgsel (); query.fields (). inkluderer ("navn"). ekskluder ("id"); Liste john = mongoTemplate.find (forespørgsel, User.class);

Disse metoder kan lænkes sammen for at inkludere eller ekskludere flere felter. Feltet markeret som @Id (_id i databasen) hentes altid, medmindre det eksplicit er ekskluderet.

Ekskluderede felter er nul i modelklasseinstansen, når poster hentes med projektion. I det tilfælde, hvor felter er af en primitiv type eller deres indpakningsklasse, er værdien af ​​ekskluderede felter standardværdier for de primitive typer.

For eksempel, Snor ville være nul, int/Heltal ville være 0 og boolsk/Boolsk ville være falsk.

Således i ovenstående eksempel er navn felt ville være John, id ville være nul og alder ville være 0.

2.2. Fremskrivninger ved hjælp af MongoRepository

Mens du bruger MongoRepositories, er felter af @Forespørgsel kommentar kan defineres i JSON-format:

@Query (værdi = "{}", felter = "{navn: 1, _id: 0}") Liste findNameAndExcludeId ();

Resultatet ville være det samme som at bruge MongoTemplate. Det værdi = ”{}” angiver ingen filtre, og derfor hentes alle dokumenter.

3. Aggregering

Aggregation i MongoDB blev bygget til at behandle data og returnere beregnede resultater. Data behandles trinvis, og output fra et trin leveres som input til næste trin. Denne evne til at anvende transformationer og foretage beregninger på data i trin gør sammenlægning til et meget kraftfuldt værktøj til analyse.

Spring Data MongoDB giver en abstraktion til native aggregationsforespørgsler ved hjælp af de tre klasser Aggregering som omslutter en aggregeringsforespørgsel, AggregationOperation som omslutter individuelle rørledningsfaser og AggregationResults som er beholderen med resultatet produceret ved aggregering.

For at udføre og aggregering skal du først oprette aggregeringsrørledninger ved hjælp af de statiske builder-metoder til Aggregering klasse, og opret derefter en forekomst af Aggregering bruger newAggregation () metode til Aggregering klasse og kør endelig aggregeringen ved hjælp af MongoTemplate:

MatchOperation matchStage = Aggregation.match (nye kriterier ("foo"). Er ("bar")); ProjectionOperation projectStage = Aggregation.project ("foo", "bar.baz"); Aggregation aggregation = Aggregation.newAggregation (matchStage, projectStage); AggregationResults output = mongoTemplate.aggregate (aggregering, "foobar", OutType.class);

Bemærk, at begge MatchOperation og Projektionsdrift implementere AggregationOperation. Der er lignende implementeringer for andre aggregeringsrørledninger. OutType er datamodellen for forventet output.

Nu vil vi se på et par eksempler og deres forklaringer til at dække de største aggregeringsrørledninger og operatører.

Datasættet, som vi bruger i denne artikel, viser detaljer om alle postnumre i USA, som kan downloades fra MongoDB-arkivet.

Lad os se på et eksempeldokument efter at have importeret det til en opkaldt samling lynlåse i prøve database.

{"_id": "01001", "city": "AGAWAM", "loc": [-72.622739, 42.070206], "pop": 15338, "state": "MA"}

Af hensyn til enkelheden og for at gøre koden kortfattet antager vi i de næste kodestykker, at alle statisk metoder til Aggregering klasse importeres statisk.

3.1. Få alle stater med en befolkning større end 10 millioner rækkefølge efter nedadgående befolkning

Her vil vi have tre rørledninger:

  1. $ gruppe fase opsummerer befolkningen i alle postnumre
  2. $ match fase for at filtrere stater med befolkning over 10 millioner
  3. $ sortering trin for at sortere alle dokumenterne i faldende rækkefølge efter befolkning

Den forventede output vil have et felt _id som stat og felt statePop med den samlede statsbefolkning. Lad os oprette en datamodel til dette og køre aggregeringen:

offentlig klasse StatePoulation {@Id privat strengstat; privat heltal statePop; // standard getters og setter}

Det @Id kommentar vil kortlægge _id felt fra output til stat i modellen:

GroupOperation groupByStateAndSumPop = group ("state") .sum ("pop"). As ("statePop"); MatchOperation filterStates = match (nye kriterier ("statePop"). Gt (10000000)); SortOperation sortByPopDesc ​​= sort (Sort.by (Retning.DESC, "statePop")); Aggregeringsaggregering = newAggregation (groupByStateAndSumPop, filterStates, sortByPopDesc); AggregationResults result = mongoTemplate.aggregate (aggregation, "zips", StatePopulation.class);

Det AggregationResults klasse redskaber Iterabel og derfor kan vi gentage det og udskrive resultaterne.

Hvis outputdatamodellen ikke er kendt, er standard MongoDB-klassen Dokument Kan bruges.

3.2. Få mindste stat efter gennemsnitlig befolkning i byen

Til dette problem har vi brug for fire faser:

  1. $ gruppe for at opsummere den samlede befolkning i hver by
  2. $ gruppe at beregne den gennemsnitlige befolkning i hver stat
  3. $ sortering scene for at ordne stater efter deres gennemsnitlige bypopulation i stigende rækkefølge
  4. $ grænse at få den første stat med den laveste gennemsnitlige befolkning i byen

Selvom det ikke nødvendigvis kræves, bruger vi en ekstra $ projekt trin for at omformatere dokumentet som ud Statens befolkning datamodel.

GroupOperation sumTotalCityPop = gruppe ("tilstand", "by"). Sum ("pop"). Som ("cityPop"); GroupOperation averageStatePop = gruppe ("_ id.state") .avg ("cityPop"). Som ("avgCityPop"); SortOperation sortByAvgPopAsc = sort (Sort.by (Direction.ASC, "avgCityPop")); LimitOperation limitToOnlyFirstDoc = limit (1); ProjectionOperation projectToMatchModel = project () .andExpression ("_ id"). Som ("state") .andExpression ("avgCityPop"). Som ("statePop"); Aggregationsaggregering = newAggregation (sumTotalCityPop, averageStatePop, sortByAvgPopAsc, limitToOnlyFirstDoc, projectToMatchModel); AggregationResults result = mongoTemplate .aggregate (aggregation, "zips", StatePopulation.class); StatePopulation smallestState = result.getUniqueMappedResult ();

I dette eksempel ved vi allerede, at der kun vil være et dokument i resultatet, da vi i sidste trin begrænser antallet af outputdokumenter til 1. Som sådan kan vi påberåbe os getUniqueMappedResult () for at få det nødvendige Statens befolkning eksempel.

En anden ting at bemærke er, at i stedet for at stole på @Id kommentar til kort _id for at sige, har vi eksplicit gjort det i projektionsfasen.

3.3. Få staten med maksimale og minimale postnummer

Til dette eksempel har vi brug for tre faser:

  1. $ gruppe at tælle antallet af postnumre for hver stat
  2. $ sortering at ordne staterne efter antallet af postnumre
  3. $ gruppe for at finde tilstanden med max og min. postnumre ved hjælp af $ først og $ sidste operatører
GroupOperation sumZips = gruppe ("tilstand"). Count (). Som ("zipCount"); SortOperation sortByCount = sort (Direction.ASC, "zipCount"); GroupOperation groupFirstAndLast = gruppe (). Første ("_ id"). Som ("minZipState"). Første ("zipCount"). Som ("minZipCount"). Sidste ("_ id"). Som ("maxZipState"). Sidste ("zipCount"). som ("maxZipCount"); Aggregation aggregering = newAggregation (sumZips, sortByCount, groupFirstAndLast); AggregationResults result = mongoTemplate .aggregate (aggregation, "zips", Document.class); Dokumentdokument = resultat.getUniqueMappedResult ();

Her har vi ikke brugt nogen model, men brugt Dokument allerede leveret med MongoDB-driver.

4. Konklusion

I denne artikel lærte vi, hvordan man henter bestemte felter i et dokument i MongoDB ved hjælp af fremskrivninger i Spring Data MongoDB.

Vi lærte også om MongoDB-aggregationsrammestøtten i Spring Data. Vi dækkede større sammenlægningsfaser - gruppere, projekt, sortere, begrænse og matche og kiggede på nogle eksempler på dets praktiske anvendelser. Den komplette kildekode er tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found