Pomocí se Připojí v MongoDB NoSQL Databází

Pomocí $vyhledávání s NoSQL

Díky Julian Motz za laskavé pomoci peer review tento článek.

jedním z největších rozdílů mezi databázemi SQL a NoSQL je JOIN. V relačních databázích umožňuje klauzule SQL JOIN kombinovat řádky ze dvou nebo více tabulek pomocí společného pole mezi nimi. Například pokud máte tabulky books a publishers, můžete psát příkazy SQL, jako například:

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

jinými slovy, tabulka book má pole publisher_id, které odkazuje na pole id v tabulce publisher.

to je praktické, protože jediný vydavatel mohl nabídnout tisíce knih. Pokud někdy potřebujeme aktualizovat údaje vydavatele, můžeme změnit jeden záznam. Redundance dat je minimalizována, protože nemusíme opakovat informace o vydavateli pro každou knihu. Tato technika je známá jako normalizace.

SQL databáze nabízejí řadu normalizačních a omezovacích funkcí, které zajišťují zachování vztahů.

NoSQL == žádné spojení?

Ne vždy …

dokumentově orientované databáze jako MongoDB jsou navrženy tak, aby ukládat nenormalizovaná data. V ideálním případě by mezi sbírkami neměl existovat žádný vztah. Pokud jsou stejné údaje vyžadovány ve dvou nebo více dokumentech, musí se opakovat.

to může být frustrující, protože existuje jen málo situací, kdy nikdy nepotřebujete relační data. Naštěstí MongoDB 3.2 představuje nový operátor $lookup, který může provádět operaci podobnou levému vnějšímu spojení na dvou nebo více kolekcích. Ale je tu háček …

MongoDB agregace

$lookup je povolena pouze v agregačních operacích. Přemýšlejte o nich jako o potrubí operátorů, které dotazují, filtrují a seskupují výsledek. Výstup jednoho operátora se používá jako vstup pro další.

agregace je obtížnější pochopit než jednodušší dotazy find a obecně bude běžet pomaleji. Jsou však výkonnými a neocenitelnými možnostmi pro složité vyhledávací operace.

agregace je nejlépe vysvětlena na příkladu. Předpokládejme, že vytváříme platformu sociálních médií s kolekcí user. Ukládá údaje každého uživatele v samostatných dokumentech. Například:

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

můžeme přidat tolik polí, kolik je třeba, ale všechny dokumenty MongoDB vyžadují pole _id, které má jedinečnou hodnotu. _id je podobný primárnímu klíči SQL a v případě potřeby bude vložen automaticky.

naše sociální síť nyní vyžaduje sbírku post, která ukládá četné zasvěcené aktualizace od uživatelů. Dokumenty ukládají text, datum, hodnocení a odkaz na uživatele, který jej napsal, do pole 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"}

nyní chceme ukázat, posledních dvacet příspěvků s „důležité“ hodnocení od všech uživatelů v obráceném chronologickém pořadí. Každý vrácený dokument by měl obsahovat text, čas příspěvku a jméno a zemi přidruženého uživatele.

MongoDB agregátní dotaz je předán pole operátorů potrubí, které definují každou operaci v pořadí. Nejprve musíme extrahovat všechny dokumenty z kolekce post, které mají správné hodnocení pomocí filtru $match :

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

nyní Musíme nějak odpovídající položky v obráceném pořadí data pomocí $sort operátor:

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

Od té doby jsme se vyžadují pouze dvacet míst, můžeme použít $limit fázi, takže MongoDB potřebuje jen zpracovat data chceme:

{ "$limit": 20 }

nyní můžeme připojit údaje z user kolekce pomocí nový $lookup operátor. To vyžaduje objekt se čtyřmi parametry:

  • localField: vyhledávací pole ve vstupním dokumentu
  • from: kolekce se připojit
  • foreignField: pole pro vyhledávání v from kolekce
  • as: název výstupního pole.

naším operátorem je proto:

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

tím se vytvoří nové pole v našem výstupu s názvem userinfo. To obsahuje pole, kde každá hodnota je odpovídající user dokumentu:

"userinfo": 

Máme one-to-one vztah mezi post.user_id a user._id, protože post může mít pouze jednoho autora. Proto naše pole userinfo bude vždy obsahovat pouze jednu položku. Operátor $unwind můžeme použít k jeho dekonstrukci do dílčího dokumentu:

{ "$unwind": "$userinfo" }

výstup bude nyní převést do praktičtější formát, který může mít další subjekty aplikovaná:

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

Konečně se můžeme vrátit text, čas, místo, jméno uživatele a země pomocí $project fáze v potrubí:

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

Dát To Všechno Dohromady

Naše konečná souhrnný dotaz odpovídá příspěvky, seřadí do pořadí, limity na nejnovější dvacet položek, připojí uživatelská data, zplošťuje uživatelská pole a vrátí potřebná pole. Plný příkaz:

db.post.aggregate();

výsledkem je sbírka až dvaceti dokumentů. Příklad:

skvělé! Konečně mohu přepnout na NoSQL!

MongoDB $lookup je užitečný a výkonný, ale i tento základní příklad vyžaduje komplexní souhrnný dotaz. Není to náhrada za výkonnější klauzuli spojení nabízenou v SQL. MongoDB také nenabízí omezení; pokud bude odstraněn dokument user, zůstanou dokumenty orphan post.

v ideálním případě by operátor $lookup měl být vyžadován zřídka. Pokud to hodně potřebujete, pravděpodobně používáte nesprávné úložiště dat…

pokud máte relační data, použijte relační (SQL) databázi!

to znamená, že $lookup je vítaným doplňkem MongoDB 3.2. To může překonat některé z více frustrující problémy při použití malého množství relačních dat v databázi NoSQL.

You might also like

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.