Utforska kraften i MongoDB:s $lookup-funktion
MongoDB, en framstående NoSQL-databas, organiserar information i samlingar. Dessa samlingar består av dokument, som var och en lagrar data i JSON-format. Dokument kan betraktas som rader i traditionella SQL-databaser, medan samlingar motsvarar tabeller.
En kärnfunktion i alla databaser är möjligheten att effektivt söka efter data. Denna förmåga möjliggör hämtning av specifik information, djupgående dataanalys, skapande av detaljerade rapporter och smidig dataintegration.
För att optimera databasfrågor är det viktigt att kunna slå samman data från flera tabeller i SQL-databaser eller samlingar i NoSQL-databaser. Detta skapar en sammanhängande resultatuppsättning.
I MongoDB erbjuder funktionen `$lookup` möjligheten att kombinera data från två olika samlingar under en fråga. Denna operation liknar en vänster yttre koppling i en SQL-databas.
Användning och mål med $lookup
Databehandling är en fundamental del av databashantering, som syftar till att utvinna meningsfull information från rådata.
Föreställ dig att du driver en restaurang. Du kan vilja analysera data för att förstå din dagliga intäkt, identifiera populära rätter under helger eller se hur många koppar kaffe som säljs varje timme.
Enkla databasfrågor räcker inte för dessa typer av analyser. Du behöver avancerade verktyg för att bearbeta dina data. MongoDB erbjuder en ”aggregeringspipeline” för att möta sådana behov.
En aggregeringspipeline är ett system som består av stegvisa operationer, där varje steg utför en specifik dataomvandling. Exempel på sådana steg är `$sort`, `$match`, `$group`, `$merge`, `$count` och `$lookup`.
Stegen i en aggregeringspipeline kan appliceras i valfri sekvens, och varje steg bearbetar datan som flödar genom pipelinen.
Alltså, `$lookup` är ett steg i MongoDB:s aggregeringspipeline. Den utför en vänster yttre koppling mellan två samlingar, vilket innebär att alla dokument från den vänstra samlingen kombineras med matchande dokument från den högra samlingen.
Låt oss illustrera detta med två exempel samlingar, presenterade i tabellformat för tydlighet:
order_collection:
order_id | customer_id | order_date | total_amount |
1 | 100 | 2022-05-01 | 50.00 |
2 | 101 | 2022-05-02 | 75.00 |
3 | 102 | 2022-05-03 | 100.00 |
kunder_samling:
customer_num | customer_name | customer_email | customer_phone |
100 | John | [email protected] | [email protected] |
Om vi utför en vänster yttre koppling på dessa samlingar baserat på fältet `customer_id` (i `order_collection`) och `customer_num` (i `customer_collection`), där `order_collection` är den vänstra samlingen, kommer resultatet att innehålla alla dokument från `order_collection` och de matchande dokumenten från `customer_collection` baserat på de relaterade fälten.
Resultatet av denna vänster yttre koppling ser ut så här:
Observera att för ordern med `customer_id` 101, som saknar en matchning i `customer_collection`, har motsvarande fält från kundtabellen fyllts med `null`.
`$lookup` utför en strikt jämförelse av likhet mellan fälten och hämtar hela dokumentet som matchar, inte bara de matchande fälten.
$lookup Syntax
Syntaxen för `$lookup` är enligt följande:
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, as: <output array field> } }
`$lookup` har fyra nyckelparametrar:
- `from` – Specifierar den samling som dokument ska hämtas från. I vårt exempel med `order_collection` och `customer_collection`, skulle `customer_collection` vara `from`-samlingen.
- `localField` – Fält i den primära samlingen som används för att jämföra med fält i `from`-samlingen. I vårt exempel skulle `localField` vara `customer_id` i `order_collection`.
- `foreignField` – Fältet i `from`-samlingen som jämförs med. I exemplet skulle detta vara `customer_num` i `customer_collection`.
- `as` – Ett nytt fältnamn för en array som innehåller alla matchande dokument från `from`-samlingen. Om inga matchningar hittas är arrayen tom.
Baserat på de tidigare samlingarna, skulle följande kod användas för att utföra en `$lookup`-operation, med `orders_collection` som primär samling.
{ $lookup: { from: "customers_collection", localField: "customer_id", foreignField: "customer_num", as: "customer_info" } }
Notera att `as`-fältet kan ha vilket strängvärde som helst. Om namnet redan används i dokumentet kommer det fältet att skrivas över.
Sammanfoga data från flera samlingar
MongoDB:s `$lookup` är ett kraftfullt steg i en aggregeringspipeline, särskilt när komplexa frågor kräver att data kombineras från flera samlingar. Även om det inte är obligatoriskt, är `$lookup` ett oumbärligt verktyg för att utföra avancerade dataanalyser.
`$lookup`-steget utför en vänster yttre koppling, vilket skapar ett nytt fält eller överskriver ett befintligt fält med en array som innehåller dokument från den anslutna samlingen. Dessa dokument väljs baserat på matchningar i jämförda fält. Resultatet är en array av dokument eller en tom array om inga matchningar hittas.
Tänk på samlingarna `employees` och `projects` nedan:
Följande kod används för att sammanfoga dessa två samlingar:
db.projects.aggregate([ { $lookup: { from: "employees", localField: "employees", foreignField: "_id", as: "assigned_employees" } } ])
Resultatet är en kombination av de två samlingarna, där varje projekt har en array av tilldelade anställda.
Pipeline Stages som kan användas tillsammans med $lookup
Som tidigare nämnts, `$lookup` är ett steg i MongoDB:s aggregeringspipeline och kan samverka med andra steg. För att illustrera detta, används följande två samlingar:
I MongoDB lagras dessa i JSON-format. Så här ser de ut i MongoDB:
Exempel på aggregeringspipelinesteg som kan användas med `$lookup` är:
$match
`$match` är ett filtersteg som begränsar dokumentflödet till de som uppfyller ett specifikt villkor. Det är bäst att använda detta steg tidigt i pipelinen för att ta bort onödiga dokument och optimera processen.
Med de tidigare samlingarna, `$match` och `$lookup` kan kombineras så här:
db.users.aggregate([ { $match: { country: "USA" } }, { $lookup: { from: "orders", localField: "_id", foreignField: "user_id", as: "orders" } } ])
Här filtrerar `$match` användare från USA, och `$lookup` lägger till detaljer om deras order. Resultatet av ovanstående operation visas nedan:
$project
`$project` omformar dokument genom att specificera vilka fält som ska inkluderas, exkluderas eller läggas till. Om du till exempel bara behöver fyra fält av tio, filtrerar `$project` ut resten. Detta undviker att onödig data överförs till nästa steg.
Kombinationen av `$lookup` och `$project` kan se ut så här:
db.users.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "user_id", as: "orders" } }, { $project: { name: 1, _id: 0, total_spent: { $sum: "$orders.price" } } } ])
Här kombinerar `$lookup` användare och ordrar, medan `$project` visar användarnamn och totalt spenderat belopp, samtidigt som fältet `_id` tas bort. Resultatet av ovanstående operation visas nedan:
$unwind
`$unwind` dekonstruerar ett arrayfält och skapar nya dokument för varje element i arrayen. Det är användbart för att utföra aggregeringar på arrayvärden.
Till exempel, om du vill aggregara information om hobbyer, måste du först använda `$unwind` eftersom `hobby` är ett arrayfält.
Med hjälp av samlingarna `users` och `orders`, kombineras `$lookup` och `$unwind` så här:
db.users.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "user_id", as: "orders" } }, { $unwind: "$orders" } ])
Här genererar `$lookup` ett arrayfält som heter `orders`. Sedan använder `$unwind` det arrayfältet. Resultatet visas nedan: Alice dyker upp två gånger eftersom hon har lagt två beställningar.
Exempel på användningsfall för $lookup
Under databearbetning är `$lookup` ett värdefullt verktyg, särskilt när du behöver sammanfoga samlingar med relaterad information. Med ett enkelt `$lookup`-steg kan du addera ett fält till primära samlingar som innehåller dokument från en annan samling.
Betrakta samlingarna `users` och `orders` nedan:
Dessa två samlingar kombineras med `$lookup` för att få resultatet nedan:
`$lookup` används även för mer komplexa joins, inte bara begränsat till två samlingar. Du kan implementera flera `$lookup`-steg för att sammanfoga mer än två samlingar. Ta dessa tre samlingar:
Följande kod sammanfogar de tre samlingarna för att visa alla order och detaljer om de beställda produkterna:
db.orders.aggregate([ { $lookup: { from: "order_items", localField: "_id", foreignField: "order_id", as: "order_items" } }, { $unwind: "$order_items" }, { $lookup: { from: "products", localField: "order_items.product_id", foreignField: "_id", as: "product_details" } }, { $group: { _id: "$_id", customer: { $first: "$customer" }, total: { $sum: "$order_items.price" }, products: { $push: "$product_details" } } } ])
Resultatet av operationen visas nedan:
Slutsats
När du bearbetar data från flera samlingar är `$lookup` ovärderligt. Det låter dig slå samman data och dra slutsatser baserat på information som lagras i olika samlingar. Databearbetning bygger sällan på bara en källa.
Att sammanfoga data över flera samlingar är viktigt för att dra meningsfulla slutsatser. Överväg därför att använda `$lookup`-steget i MongoDBs aggregeringspipeline för att bättre bearbeta din data och få insikter från information lagrad i olika samlingar.
Du kan också utforska andra MongoDB-kommandon och frågor.