datorită Julian Motz pentru a ajuta cu amabilitate la peer review acest articol.
una dintre cele mai mari diferențe dintre bazele de date SQL și NoSQL este JOIN. În bazele de date relaționale, clauza SQL JOIN vă permite să combinați rânduri din două sau mai multe tabele folosind un câmp comun între ele. De exemplu, dacă aveți tabele de books
și publishers
, puteți scrie comenzi SQL, cum ar fi:
SELECT book.title, publisher.nameFROM bookLEFT JOIN book.publisher_id ON publisher.id;
cu alte cuvinte, tabelul book
are un câmp publisher_id
care face referire la câmpul id
din tabelul publisher
.
acest lucru este practic, deoarece un singur editor ar putea oferi mii de cărți. Dacă vreodată trebuie să actualizăm detaliile unui editor, putem schimba o singură înregistrare. Redundanța datelor este minimizată, deoarece nu este nevoie să repetăm informațiile editorului pentru fiecare carte. Tehnica este cunoscută sub numele de normalizare.
bazele de date SQL oferă o serie de caracteristici de normalizare și constrângere pentru a asigura menținerea relațiilor.
NoSQL == nu se alăture?
nu întotdeauna …
baze de date orientate spre documente, cum ar fi MongoDB, sunt concepute pentru a stoca date denormalizate. În mod ideal, nu ar trebui să existe nicio relație între colecții. Dacă aceleași date sunt necesare în două sau mai multe documente, acestea trebuie repetate.
acest lucru poate fi frustrant, deoarece există puține situații în care nu aveți nevoie niciodată de date relaționale. Din fericire, MongoDB 3.2 introduce un nou operator $lookup
care poate efectua o operație asemănătoare alăturării la stânga pe două sau mai multe colecții. Dar există o captură …
agregarea MongoDB
$lookup
este permisă numai în operațiunile de agregare. Gândiți-vă la acestea ca la o conductă de operatori care interoghează, filtrează și grupează un rezultat. Ieșirea unui operator este utilizată ca intrare pentru următorul.
agregarea este mai dificil de înțeles decât interogările mai simple find
și, în general, va rula mai lent. Cu toate acestea, ele sunt puternice și o opțiune neprețuită pentru operațiuni complexe de căutare.
agregarea este cel mai bine explicată cu un exemplu. Presupunem că creăm o platformă de socializare cu o colecție user
. Stochează detaliile fiecărui utilizator în documente separate. De exemplu:
{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email: "[email protected]", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z")}
putem adăuga cât mai multe câmpuri necesare, dar toate documentele MongoDB necesită un câmp _id
care are o valoare unică. _id
este similar cu o cheie primară SQL și va fi inserat automat dacă este necesar.
rețeaua noastră socială necesită acum o colecție post
, care stochează numeroase actualizări intuitive de la utilizatori. Documentele stochează textul, data, o evaluare și o referință la utilizatorul care a scris-o într-un câmp user_id
:
{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date: ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important"}
acum vrem să arătăm ultimele douăzeci de postări cu un rating „important” de la toți utilizatorii în ordine cronologică inversă. Fiecare document returnat trebuie să conțină textul, ora postării și numele și țara utilizatorului asociat.
interogarea agregată MongoDB este transmisă o serie de operatori de conducte care definesc fiecare operație în ordine. În primul rând, trebuie să extragem toate documentele din colecția post
care au ratingul corect folosind filtrul $match
:
{ "$match": { "rating": "important" } }
acum trebuie să sortăm elementele potrivite în ordine inversă a datei folosind operatorul $sort
:
{ "$sort": { "date": -1 } }
din moment ce avem nevoie doar de douăzeci de posturi, putem aplica o $limit
etapă, astfel MongoDB are nevoie doar pentru a procesa datele pe care le dorim:
{ "$limit": 20 }
acum ne putem alătura datelor din colecția user
folosind noul operator $lookup
. Este nevoie de un obiect cu patru parametri:
-
localField
: câmpul de căutare din documentul de intrare -
from
: colecția să se alăture -
foreignField
: câmpul de căutare în colecțiafrom
-
as
: numele câmpului de ieșire.
operatorul nostru este, prin urmare:
{ "$lookup": { "localField": "user_id", "from": "user", "foreignField": "_id", "as": "userinfo"} }
aceasta va crea un câmp nou în rezultatul nostru numit userinfo
. Acesta conține o matrice în cazul în care fiecare valoare este de potrivire user
documentul:
"userinfo":
avem o relație unu-la-unu între post.user_id
și user._id
, deoarece o postare poate avea un singur autor. Prin urmare, matricea noastră userinfo
va conține doar un singur element. Putem folosi operatorul $unwind
pentru a-l deconstrui într-un sub-document:
{ "$unwind": "$userinfo" }
ieșirea va fi acum convertită într-un format mai practic, care poate avea operatori suplimentari aplicați:
"userinfo": { "name": "User One", "email: "[email protected]", …}
în cele din urmă, putem returna textul, ora postării, numele și țara utilizatorului folosind o etapă $project
în conductă:
{ "$project": { "text": 1, "date": 1, "userinfo.name": 1, "userinfo.country": 1} }
punând totul împreună
interogarea noastră agregată finală se potrivește cu postările, Sortează în ordine, limitează la cele mai recente douăzeci de articole, unește datele utilizatorului, aplatizează matricea utilizatorului și returnează doar câmpurile necesare. Comanda completă:
db.post.aggregate();
rezultatul este o colecție de până la douăzeci de documente. De exemplu:
grozav! În sfârșit pot trece la NoSQL!
MongoDB $lookup
este util și puternic, dar chiar și acest exemplu de bază necesită o interogare agregată complexă. Nu este un substitut pentru clauza JOIN mai puternică oferită în SQL. Nici MongoDB nu oferă constrângeri; dacă un document user
este șters, documentele orfane post
ar rămâne.
în mod ideal, operatorul $lookup
ar trebui să fie solicitat rar. Dacă aveți nevoie foarte mult, este posibil să utilizați un magazin de date greșit…
dacă aveți date relaționale, utilizați o bază de date relațională (SQL)!
acestea fiind spuse, $lookup
este o adăugare binevenită la MongoDB 3.2. Poate depăși unele dintre problemele mai frustrante atunci când se utilizează cantități mici de date relaționale într-o bază de date NoSQL.