using JOINs in MongoDB NoSQL Databases

Using $lookUp with NoSQL

Thanks to Julian Motz for Applied helping to peer review this article.

yksi suurimmista eroista SQL-ja NoSQL-tietokantojen välillä on JOIN. Relaatiotietokannoissa SQL JOIN-lausekkeen avulla voi yhdistää rivejä kahdesta tai useammasta taulukosta käyttäen niiden välistä yhteistä kenttää. Jos sinulla on esimerkiksi taulukot books ja publishers, voit kirjoittaa SQL-komentoja kuten:

SELECT book.title, publisher.nameFROM bookLEFT JOIN book.publisher_id ON publisher.id;

toisin sanoen book taulukossa on publisher_id kenttä, joka viittaa id kenttään publisher taulukossa.

tämä on käytännöllistä, sillä yksi Kustantaja voisi tarjota tuhansia kirjoja. Jos joskus pitää päivittää julkaisijan tietoja, voimme muuttaa yhtä levyä. Tietojen redundanssi on minimoitu, koska meidän ei tarvitse toistaa julkaisijan tiedot jokaisen kirjan. Tekniikka tunnetaan nimellä normalisointi.

SQL-tietokannoissa on useita normalisointi-ja rajoitusominaisuuksia, joilla varmistetaan suhteiden säilyminen.

NoSQL = = ei liity?

ei aina …

asiakirjoihin perustuvat tietokannat, kuten MongoDB, on suunniteltu tallentamaan denormalisoitua tietoa. Ihannetapauksessa kokoelmien välillä ei pitäisi olla mitään suhdetta. Jos samat tiedot vaaditaan kahdessa tai useammassa asiakirjassa, ne on toistettava.

tämä voi olla turhauttavaa, sillä on harvoja tilanteita, joissa ei koskaan tarvitsisi relaatiotietoja. Onneksi MongoDB 3.2 tuo markkinoille uuden $lookup-operaattorin, joka voi suorittaa vasemmalle ULOIMMAISEN liitoksen kaltaisen operaation kahdella tai useammalla kokoelmalla. Mutta siinä on juju …

MongoDB aggregointi

$lookup on sallittua vain aggregointioperaatioissa. Ajattele näitä operaattoreiden putkena, jotka kyselevät, suodattavat ja ryhmittelevät tulosta. Yhden toimijan ulostuloa käytetään seuraavan tulona.

aggregointi on vaikeaselkoisempi kuin yksinkertaisemmat find kyselyt ja ne kulkevat yleensä hitaammin. Ne ovat kuitenkin tehokkaita ja korvaamaton vaihtoehto monimutkaisissa etsintäoperaatioissa.

aggregaatio selittyy parhaiten esimerkillä. Oletamme, että luomme sosiaalisen median alustan user – kokoelmalla. Se tallentaa jokaisen käyttäjän tiedot erillisiin asiakirjoihin. Esimerkiksi:

{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email: "[email protected]", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z")}

voimme lisätä niin monta kenttää kuin on tarpeen, mutta kaikki MongoDB-dokumentit edellyttävät _id kenttää, jolla on ainutlaatuinen arvo. _id on samanlainen kuin SQL-ensisijainen avain, ja se lisätään tarvittaessa automaattisesti.

yhteisöpalvelumme vaatii nyt post – kokoelman, johon on tallennettu lukuisia oivaltavia päivityksiä käyttäjiltä. Dokumentit tallentavat tekstin, päivämäärän, arvosanan ja viitteen sen kirjoittaneeseen käyttäjään user_id – kenttään:

{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date: ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important"}

haluamme nyt näyttää viimeiset kaksikymmentä virkaa, joissa on” tärkeä ” luokitus kaikilta käyttäjiltä käänteisessä aikajärjestyksessä. Jokaisen palautetun asiakirjan tulee sisältää teksti, postauksen ajankohta ja siihen liittyvän käyttäjän nimi ja maa.

MongoDB-aggregaattikysely läpäisee joukon putkijohtajia, jotka määrittelevät jokaisen operaation järjestyksessä. Ensinnäkin meidän täytyy poimia kaikki asiakirjat post kokoelma, joilla on oikea luokitus käyttäen $match suodatin:

{ "$match": { "rating": "important" } }

meidän on nyt järjestettävä täsmäytetyt erät käänteiseen päiväysjärjestykseen käyttäen $sort – operaattoria:

{ "$sort": { "date": -1 } }

koska tarvitsemme vain kaksikymmentä virkaa, voimme soveltaa $limit – vaihetta, joten MongoDB tarvitsee vain käsitellä haluamaamme tietoa:

{ "$limit": 20 }

user – keräyksen tietoja voi nyt yhdistää uudella $lookup – operaattorilla. Se vaatii objektin, jolla on neljä parametria:

  • localField: hakukenttä syöteasiakirjassa
  • from: keräys mukaan
  • foreignField: etsittävä kenttä from kokoelmassa
  • as: lähtökentän nimi.

operaattorimme on siis:

{ "$lookup": { "localField": "user_id", "from": "user", "foreignField": "_id", "as": "userinfo"} }

tämä luo tulostamme uuden kentän, jonka nimi on userinfo. Se sisältää taulukon, jossa jokainen arvo on vastaava user asiakirja:

"userinfo": 

post.user_id: n ja user._id: n välillä on kahdenkeskinen suhde, sillä postauksessa voi olla vain yksi tekijä. Siksi meidän userinfo array sisältää vain yhden kohteen. Voimme käyttää $unwind – operaattoria purkamaan sen alidokumentiksi:

{ "$unwind": "$userinfo" }

tuotos muutetaan nyt käytännöllisempään muotoon, jossa voidaan soveltaa uusia toimijoita:

"userinfo": { "name": "User One", "email: "[email protected]", …}

lopuksi voimme palauttaa tekstin, postausajan, käyttäjän nimen ja maan käyttämällä $project – vaihetta valmisteilla:

{ "$project": { "text": 1, "date": 1, "userinfo.name": 1, "userinfo.country": 1} }

kaikki yhteenlaskettuna

lopullinen koostekyselymme täsmää viesteihin, lajittelee järjestykseen, rajoittaa viimeisintä kahtakymmentä kohdetta, yhdistää käyttäjätiedot, litistää käyttäjäryhmän ja palauttaa vain tarvittavat kentät. The full command:

db.post.aggregate();

tuloksena on jopa kahdenkymmenen dokumentin kokoelma. Esimerkiksi:

hienoa! Voin vihdoin vaihtaa NoSQL!

MongoDB $lookup on hyödyllinen ja tehokas, mutta tämäkin perusesimerkki vaatii monimutkaisen aggregaattikyselyn. Se ei korvaa tehokkaampi liittyä lauseke tarjotaan SQL. Myöskään MongoDB ei tarjoa rajoitteita; jos user asiakirja poistetaan, orphan post asiakirjat jäisivät jäljelle.

Ihannetapauksessa $lookup – operaattoria tarvitaan harvoin. Jos tarvitset sitä paljon, käytät mahdollisesti väärää tietovarastoa …

jos sinulla on relaatiotietoja, käytä relaatiotietokantaa (SQL)!

näin ollen $lookup on tervetullut lisä MongoDB 3.2: een. Se voi voittaa joitakin turhauttavaa kysymyksiä käytettäessä pieniä määriä relaatiotietoja NoSQL-tietokantaan.

You might also like

Vastaa

Sähköpostiosoitettasi ei julkaista.