Forespørgsel om Couchbase med MapReduce Views

1. Oversigt

I denne vejledning introducerer vi nogle enkle MapReduce-visninger og demonstrerer, hvordan man spørger dem ved hjælp af Couchbase Java SDK.

2. Maven-afhængighed

Hvis du vil arbejde med Couchbase i et Maven-projekt, skal du importere Couchbase SDK til din pom.xml:

 com.couchbase.client java-klient 2.4.0 

Du kan finde den nyeste version på Maven Central.

3. MapReduce Views

I Couchbase er en MapReduce-visning en type indeks, der kan bruges til at forespørge om en dataspand. Det defineres ved hjælp af JavaScript kort funktion og en valgfri reducere fungere.

3.1. Det kort Fungere

Det kort funktion køres mod hvert dokument en gang. Når visningen oprettes, vises kort -funktionen køres en gang mod hvert dokument i spanden, og resultaterne gemmes i spanden.

Når en visning er oprettet, kort funktionen køres kun mod nyindsatte eller opdaterede dokumenter for at opdatere visningen trinvist.

Fordi kort funktionens resultater er gemt i dataspanden, forespørgsler mod en visning udviser lave latenstider.

Lad os se på et eksempel på en kort funktion, der opretter et indeks på navn felt med alle dokumenter i spanden, hvis type felt er lig med “StudentGrade”:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.name) {emit (doc.name, null); }}

Det udsender funktion fortæller Couchbase hvilke datafelt (er) der skal gemmes i indeksnøglen (første parameter) og hvilken værdi (anden parameter) der skal tilknyttes det indekserede dokument.

I dette tilfælde gemmer vi kun dokumentet navn ejendom i indeksnøglen. Og da vi ikke er interesseret i at knytte nogen særlig værdi til hver post, videregiver vi nul som værdiparameter.

Når Couchbase behandler visningen, oprettes det et indeks over de nøgler, der udsendes af kort funktion, der knytter hver nøgle til alle dokumenter, som nøglen blev udsendt for.

For eksempel, hvis tre dokumenter har navn ejendom indstillet til “John Doe”, derefter indeksnøglen “John Doe” ville være knyttet til disse tre dokumenter.

3.2. Det reducere Fungere

Det reducere funktion bruges til at udføre samlede beregninger ved hjælp af resultaterne af a kort fungere. Couchbase Admin UI giver en nem måde at anvende den indbyggede på reducere funktioner “_Count”, “_sum”, og “_Statistik”, til din kort fungere.

Du kan også skrive din egen reducere funktioner til mere komplekse sammenlægninger. Vi vil se eksempler på brug af den indbyggede reducere fungerer senere i vejledningen.

4. Arbejde med synspunkter og forespørgsler

4.1. Organisering af udsigterne

Visninger er organiseret i et eller flere designdokumenter pr. Spand. I teorien er der ingen grænse for antallet af visninger pr. Designdokument. For at opnå optimal ydelse er det dog blevet foreslået, at du skal begrænse hvert designdokument til færre end ti visninger.

Når du først opretter en visning i et designdokument, angiver Couchbase det som en udvikling udsigt. Du kan køre forespørgsler mod en udvikling visning for at teste dens funktionalitet. Når du er tilfreds med udsigten, ville du offentliggøre designdokumentet, og udsigten bliver til produktion udsigt.

4.2. Konstruktion af forespørgsler

For at konstruere en forespørgsel mod en Couchbase-visning skal du angive dens designdokumentnavn og visningsnavn for at oprette en ViewQuery objekt:

ViewQuery-forespørgsel = ViewQuery.from ("design-document-name", "view-name");

Når den udføres, returnerer denne forespørgsel alle rækker i visningen. Vi vil se i senere afsnit, hvordan man begrænser resultatsættet baseret på nøgleværdierne.

For at konstruere en forespørgsel mod en udviklingsvisning kan du anvende udvikling() metode, når du opretter forespørgslen:

ViewQuery-forespørgsel = ViewQuery.from ("design-doc-name", "view-name"). Udvikling ();

4.3. Udførelse af forespørgslen

Når vi har en ViewQuery objekt, kan vi udføre forespørgslen for at få et Vis resultat:

ViewResult resultat = bucket.query (forespørgsel);

4.4. Behandler forespørgselsresultater

Og nu hvor vi har en Vis resultat, kan vi gentage sig over rækkerne for at få dokument-id'er og / eller indhold:

for (ViewRow række: result.allRows ()) {JsonDocument doc = row.document (); Streng-id = doc.id (); String json = doc.content (). ToString (); }

5. Eksempel på anvendelse

I den resterende del af selvstudiet skriver vi MapReduce-visninger og forespørgsler til et sæt studerendes klassedokumenter med følgende format med karakterer begrænset til området 0 til 100:

{"type": "StudentGrade", "name": "John Doe", "course": "History", "hours": 3, "grade": 95}

Vi gemmer disse dokumenter i “baeldung-tutorial”Spand og alle visninger i et designdokument med navnet”studentKlasser. ” Lad os se på den kode, der er nødvendig for at åbne skovlen, så vi kan spørge den:

Bucket bucket = CouchbaseCluster.create ("127.0.0.1") .openBucket ("baeldung-tutorial");

6. Nøjagtige matchforespørgsler

Antag, at du vil finde alle studerendes karakterer til et bestemt kursus eller sæt af kurser. Lad os skrive en visning kaldet “findByCourse”Ved hjælp af følgende kort fungere:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.course && doc.grade) {emit (doc.course, null); }}

Bemærk, at i denne enkle visning behøver vi kun at udsende Rute Mark.

6.1. Matching på en enkelt nøgle

For at finde alle karakterer til kurset Historie anvender vi nøgle metode til vores basisforespørgsel:

ViewQuery-forespørgsel = ViewQuery.from ("studentGrades", "findByCourse"). Nøgle ("History");

6.2. Matchning på flere taster

Hvis du vil finde alle karakterer til matematik og naturvidenskabskurser, kan du anvende nøgler metode til basisforespørgslen og videregiver den en række nøgleværdier:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "findByCourse"). Nøgler (JsonArray.from ("Math", "Science"));

7. Område forespørgsler

For at forespørge efter dokumenter, der indeholder en række værdier for et eller flere felter, har vi brug for en visning, der udsender det eller de felt, vi er interesseret i, og vi skal angive en nedre og / eller øvre grænse for forespørgslen.

Lad os se på, hvordan man udfører rækkeforespørgsler, der involverer et enkelt felt og flere felter.

7.1. Forespørgsler, der involverer et enkelt felt

For at finde alle dokumenter med en række karakter værdier uanset værdien af Rute felt, har vi brug for en visning, der kun udsender karakter Mark. Lad os skrive kort funktion til “findByGrade”Visning:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.grade) {emit (doc.grade, null); }}

Lad os skrive en forespørgsel i Java ved hjælp af denne visning for at finde alle karakterer svarende til en "B" bogstavkarakter (inklusive 80 til 89):

ViewQuery-forespørgsel = ViewQuery.from ("studentGrades", "findByGrade") .startKey (80) .endKey (89) .inclusiveEnd (true);

Bemærk, at startnøgleværdien i en rækkeforespørgsel altid behandles som inkluderende.

Og hvis alle karakterer vides at være heltal, giver følgende forespørgsel de samme resultater:

ViewQuery-forespørgsel = ViewQuery.from ("studentGrades", "findByGrade") .startKey (80) .endKey (90) .inclusiveEnd (false);

For at finde alle “A” -karakterer (90 og derover) behøver vi kun at specificere den nedre grænse:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "findByGrade") .startKey (90);

Og for at finde alle manglende karakterer (under 60) behøver vi kun at angive den øvre grænse:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "findByGrade") .endKey (60) .inclusiveEnd (false);

7.2. Forespørgsler, der involverer flere felter

Antag nu, at vi vil finde alle studerende på et bestemt kursus, hvis karakter falder inden for et bestemt interval. Denne forespørgsel kræver en ny visning, der udsender både Rute og karakter felter.

Med visninger med flere felter udsendes hver indeksnøgle som en række værdier. Da vores forespørgsel indebærer en fast værdi for Rute og en række karakter værdier, vi skriver kortfunktionen for at udsende hver tast som en matrix af formularen [Rute, karakter].

Lad os se på kort funktion til visningen “findByCourseAndGrade“:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.course && doc.grade) {emit ([doc.course, doc.grade], null); }}

Når denne visning er udfyldt i Couchbase, sorteres indeksindgangene efter Rute og karakter. Her er et undersæt af nøgler i “findByCourseAndGrade”Visning vist i deres naturlige sorteringsrækkefølge:

["Historie", 80] ["Historie", 90] ["Historie", 94] ["Matematik", 82] ["Matematik", 88] ["Matematik", 97] ["Videnskab", 78] [ "Videnskab", 86] ["Videnskab", 92]

Da tasterne i denne visning er arrays, vil du også bruge arrays i dette format, når du angiver den nedre og den øvre grænse for en rækkeforespørgsel mod denne visning.

Dette betyder, at for at finde alle studerende, der fik karakteren "B" (80 til 89) i matematikfaget, ville du sætte den nedre grænse til:

["Matematik", 80]

og den øvre grænse til:

["Matematik", 89]

Lad os skrive rækkefølgen i Java:

ViewQuery forespørgsel = ViewQuery .from ("studentGrades", "findByCourseAndGrade") .startKey (JsonArray.from ("Math", 80)) .endKey (JsonArray.from ("Math", 89)) .inclusiveEnd (true);

Hvis vi vil finde for alle studerende, der fik karakteren "A" (90 og derover) i matematik, ville vi skrive:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "findByCourseAndGrade"). StartKey (JsonArray.from ("Math", 90)) .endKey (JsonArray.from ("Math", 100));

Bemærk, at fordi vi sætter kursværdien på “Matematik“, Vi skal medtage en øvre grænse med den højest mulige karakter værdi. Ellers vil vores resultatsæt også omfatte alle dokumenter, hvis Rute værdi er leksikografisk større end “Matematik“.

Og for at finde alle manglende matematikkarakterer (under 60):

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "findByCourseAndGrade"). StartKey (JsonArray.from ("Math", 0)) .endKey (JsonArray.from ("Math", 60)) .inclusiveEnd (false);

I lighed med det foregående eksempel skal vi specificere en nedre grænse med den lavest mulige karakter. Ellers vil vores resultatsæt også omfatte alle karakterer, hvor Rute værdi er leksikografisk mindre end “Matematik“.

Endelig kan du fortælle Couchbase at udføre en faldende sortering og begrænse resultatsættets størrelse for at finde de fem højeste matematiske karakterer (uden spændinger).

ViewQuery-forespørgsel = ViewQuery .from ("studentGrades", "findByCourseAndGrade"). Faldende () .startKey (JsonArray.from ("Math", 100)) .endKey (JsonArray.from ("Math", 0)) .inclusiveEnd ( sand) .begrænsning (5);

Bemærk, at når du udfører en faldende sortering, startKey og endKey værdier vendes, fordi Couchbase anvender sorteringen, inden den anvender begrænse.

8. Samlede forespørgsler

En vigtig styrke ved MapReduce-visninger er, at de er meget effektive til at køre samlede forespørgsler mod store datasæt. I vores datasæt for studenterkarakterer kan vi for eksempel nemt beregne følgende aggregater:

  • antal studerende på hvert kursus
  • sum af kredit timer for hver studerende
  • karaktergennemsnit for hver studerende på tværs af alle kurser

Lad os oprette en visning og forespørgsel for hver af disse beregninger ved hjælp af indbygget reducere funktioner.

8.1. Bruger tælle() Fungere

Lad os først skrive kort funktion til visning til at tælle antallet af studerende på hvert kursus:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.course && doc.name) {emit ([doc.course, doc.name], null); }}

Vi kalder denne visning “countStudentsByCourse”Og angive, at det er at bruge den indbyggede "_tælle" fungere. Og da vi kun udfører en simpel optælling, kan vi stadig udsende nul som værdien for hver post.

At tælle antallet af studerende på hvert kursus:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "countStudentsByCourse") .reduce () .groupLevel (1);

Uddrag af data fra samlede forespørgsler er forskellig fra det, vi har set indtil nu. I stedet for at udtrække et matchende Couchbase-dokument for hver række i resultatet udpakker vi de samlede nøgler og resultater.

Lad os køre forespørgslen og udtrække tællingerne i en java.util.Kort:

ViewResult resultat = bucket.query (forespørgsel); Kort numStudentsByCourse = ny HashMap (); for (ViewRow række: result.allRows ()) {JsonArray keyArray = (JsonArray) række.key (); Strengkursus = keyArray.getString (0); lang optælling = Long.valueOf (row.value (). toString ()); numStudentsByCourse.put (kursus, antal); }

8.2. Bruger sum() Fungere

Lad os derefter skrive en visning, der beregner summen af ​​hver studerendes kreditforsøg. Vi kalder denne visning “sumHoursByStudent”Og angive, at det er at bruge den indbyggede "_sum" fungere:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.name && doc.course && doc.hours) {emit ([doc.name, doc.course], doc.hours); }}

Bemærk, at når du anvender "_sum" funktion, skal vi udsender den værdi, der skal opsummeres - i dette tilfælde antallet af kreditter - for hver post.

Lad os skrive en forespørgsel for at finde det samlede antal point for hver studerende:

ViewQuery-forespørgsel = ViewQuery. Fra ("studentGrades", "sumCreditsByStudent") .reduce () .groupLevel (1);

Og nu, lad os køre forespørgslen og udtrække de samlede summer til en java.util.Kort:

ViewResult resultat = bucket.query (forespørgsel); Kort hoursByStudent = ny HashMap (); for (ViewRow række: result.allRows ()) {String name = (String) row.key (); lang sum = Long.valueOf (row.value (). toString ()); hoursByStudent.put (navn, sum); }

8.3. Beregning af gennemsnitsværdier

Antag, at vi vil beregne hver studerendes karakterpoint-gennemsnit (GPA) på tværs af alle kurser ved hjælp af den konventionelle karakterskala baseret på de opnåede karakterer og antallet af kredit-timer, som kurset er værd (A = 4 point pr. Kredit time, B = 3 point pr. Kredit time, C = 2 point pr. Kredit time, og D = 1 point pr. Kredit time).

Der er ingen indbygget reducere funktion til at beregne gennemsnitsværdier, så vi kombinerer output fra to visninger for at beregne GPA.

Vi har allerede den “SumHoursByStudent” visning, der summerer antallet af kredit timer, hver studerende forsøgte. Nu har vi brug for det samlede antal karakterpoint, som hver elev har optjent.

Lad os oprette en visning kaldet “SumGradePointsByStudent” der beregner antallet af optjente karakterpoint for hvert kursus, der er taget. Vi bruger den indbyggede "_sum" funktion for at reducere følgende kort fungere:

funktion (doc, meta) {if (doc.type == "StudentGrade" && doc.name && doc.hours && doc.grade) {if (doc.grade> = 90) {emit (doc.name, 4 * doc . timer); } ellers hvis (doc.grad> = 80) {emit (doc.name, 3 * doc.hours); } ellers hvis (doc.grad> = 70) {emit (doc.name, 2 * doc.hours); } ellers hvis (doc.grad> = 60) {emit (doc.name, doc.hours); } andet {emit (doc.name, 0); }}}

Lad os nu spørge denne visning og udtrække summerne til a java.util.Kort:

ViewQuery-forespørgsel = ViewQuery.from ("studentGrades", "sumGradePointsByStudent") .reduce () .groupLevel (1); ViewResult resultat = bucket.query (forespørgsel); Map gradePointsByStudent = ny HashMap (); for (ViewRow række: result.allRows ()) {String kursus = (String) række.key (); lang sum = Long.valueOf (row.value (). toString ()); gradePointsByStudent.put (kursus, sum); }

Lad os endelig kombinere de to Korts for at beregne GPA for hver studerende:

Kortresultat = nyt HashMap (); for (Entry creditHoursEntry: hoursByStudent.entrySet ()) {String name = creditHoursEntry.getKey (); lang totalHours = kreditHoursEntry.getValue (); lang totalGradePoints = gradePointsByStudent.get (navn); result.put (navn, ((float) totalGradePoints / totalHours)); }

9. Konklusion

Vi har demonstreret, hvordan man skriver nogle grundlæggende MapReduce-visninger i Couchbase, og hvordan man konstruerer og udfører forespørgsler mod visningerne og udtrækker resultaterne.

Koden, der præsenteres i denne vejledning, kan findes i GitHub-projektet.

Du kan lære mere om MapReduce-visninger og hvordan man forespørger dem i Java på det officielle Couchbase-udviklingsdokumentationswebsted.


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