Hur man använder $lookup i MongoDB

MongoDB är en populär NoSQL-databas som lagrar data i samlingar. MongoDB-samlingar består av ett eller flera dokument som innehåller själva data i JSON-format. Dokument är jämförbara med rader i traditionella relationella SQL-databaser, medan samlingar är analoga med tabeller.

En nyckelfunktion i databaser är möjligheten att fråga efter data som lagras i databasen. Att söka efter data möjliggör hämtning av specifik information, dataanalys, datarapportering och även dataintegration.

För att kunna fråga en databas effektivt är det avgörande att kunna kombinera data från flera tabeller, i fallet med SQL-databaser eller flera samlingar i NOSQL-databaser, till en enda resultatuppsättning.

I MongoDB $lookup användare att kombinera information från två samlingar när de frågar. Den utför motsvarande en vänster yttre koppling i en SQL-databas.

$lookups användning och mål

En viktig funktion hos databaser är databehandling för att få ut meningsfull information ur rådata.

Om du till exempel driver ett restaurangföretag kanske du vill analysera din restaurangs data för att ta reda på hur mycket du tjänar varje dag, vilken mat som efterfrågas på helgerna, eller till och med ta reda på hur många koppar kaffe du säljer på varje timme på dygnet.

För sådana behov kommer enkla databasfrågor inte att räcka. Du måste utföra avancerade frågor på den data du har lagrat. För att möta sådana behov har MongoDB en funktion som kallas en aggregeringspipeline.

En aggregeringspipeline är ett system som består av komponerbara operationer som kallas steg, som används för att bearbeta data för att producera ett slutligt aggregerat resultat. Exempel på steg i aggregeringspipelinen inkluderar bland annat $sort, $match, $group, $merge, $count och $lookup.

Dessa steg kan tillämpas i valfri ordning i en aggregeringspipeline. I varje steg i en aggregeringspipeline utförs olika operationer på data som skickas genom aggregeringspipelinen.

$lookup är alltså ett steg i MongoDB:s aggregeringspipeline. $Lookup används för att utföra en vänster yttre koppling mellan två samlingar i en MongoDB-databas. En vänster yttre sammanfogning kombinerar alla dokument eller poster till vänster med matchande dokument eller poster till höger.

Tänk till exempel på de två samlingarna nedan, som har representerats i tabellformat för enklare förståelse:

order_collection:

order_idcustomer_idorder_datetotal_amount11002022-05-0150.0021012022-05-0275.0031022022-05-03100.00

kunder_samling:

customer_numcustomer_namecustomer_emailcustomer_phone100John [email protected] [email protected]

Om vi ​​utför en vänster yttre sammanfogning på ovanstående samlingar med hjälp av kund_id-fältet, som visas i order_collection, där order_collection är den vänstra samlingen och customer_collection är den högra samlingen, kommer resultatet att innehålla alla dokument i Order Collection och dokument på Customers Collection som har ett customer_num som matchar ett customer_id för någon av posterna i Order Collection.

Det slutliga resultatet av den vänstra yttre sammanfogningen på beställningarna och kundkollektionerna ser ut så här när de visas i tabellformat:

Observera att för kunden med kund-id 101 i ordersamlingen, som inte hade något matchande värde för kundnummer i kundsamlingen, har saknade motsvarande värden från kundtabellen fyllts med null.

$lookup utför strikt jämställdhetsjämförelse mellan fält och hämtar hela dokumentet som matchade, och inte bara de fält som matchade.

$lookup Syntax

Syntaxen för $lookup är 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 parametrar:

  • från – representerar samlingen från vilken vi vill söka upp dokument. I vårt tidigare exempel med order_collection och customer_collection, skulle vi lägga till customer_collection som från samlingen.
  • localField – detta är ett fält i den fungerande eller primära samlingen som vi använder för att jämföra med fält i vår från-samling (customers_collection i vårt fall). I exemplet ovan skulle localField vara customer_id som finns i orders_collection.
  • foreignField – det här är fältet vi vill jämföra med i samlingen vi specificerar i från. I vårt exempel skulle detta vara customer_num som finns i customer_collection som vi använder som vårt värde i från
  • as – detta är ett nytt fältnamn som vi anger för att representera fältet som kommer att dyka upp i vårt dokument, som innehåller dokument som härrör från matchningar mellan det lokala fältet och det främmande fältet. Alla dessa matchningar placeras i en array i detta fält. Om det inte finns några matchningar kommer detta fält att innehålla en tom array.

Från våra två tidigare samlingar skulle vi använda följande kod för att utföra en $lookup-operation på de två samlingarna med orders_collection som vår fungerande eller primära samling.

{
    $lookup: {
      from: "customers_collection",
      localField: "customer_id",
      foreignField: "customer_num",
      as: "customer_info"
 }

Observera att as-fältet kan vara vilket strängvärde som helst. Men om du ger det ett namn som redan finns i arbetsdokumentet kommer det fältet att skrivas över.

Sammanfoga data från flera samlingar

MongoDB $lookup är ett användbart steg i en aggregeringspipeline i MongoDB. Även om det inte är ett krav att en aggregeringspipeline i MongoDB måste ha ett $lookup-steg, är steget avgörande när man utför komplexa frågor som kräver sammanfogning av data över flera samlingar.

$lookup-steget utför en vänster yttre koppling på två samlingar vilket resulterar i att ett nytt fält skapas eller att ett befintligt fälts värden skrivs över med en array som innehåller dokument från en annan samling.

Dessa dokument väljs utifrån om de har värden som matchar värdena i fältet de jämförs med. Slutresultatet är ett fält som innehåller en array av dokument om matchningar hittades eller en tom array om inga matchningar hittades.

Tänk på de anställdas och projektsamlingar som visas nedan.

Vi kan använda följande kod för att gå med i de två samlingarna:

db.projects.aggregate([
   {
      $lookup: {
         from: "employees",
         localField: "employees",
         foreignField: "_id",
         as: "assigned_employees"
      }
   }
])

Resultatet av denna operation är en kombination av de två samlingarna. Resultatet är projekten och alla anställda som tilldelas varje projekt. De anställda är representerade i en array.

Pipeline Stages som kan användas tillsammans med $lookup

Som nämnts tidigare är $lookup ett steg i en MongoDB-aggregationspipeline, och det kan användas tillsammans med andra aggregeringspipelinesteg. För att visa hur dessa stadier kan användas tillsammans med $lookup, kommer vi att använda följande två samlingar i illustrationssyfte.

I MongoDB lagras de i JSON-format. Så här ser ovanstående samlingar ut i MongoDB.

Några exempel på aggregeringspipelinesteg som kan användas tillsammans med $lookup inkluderar:

$match

$match är ett aggregeringspipelinesteg som används för att filtrera dokumentströmmen så att endast de dokument som uppfyller det givna villkoret kan gå vidare till nästa steg i aggregeringspipelinen. Detta steg används bäst tidigt i pipelinen för att ta bort dokument som inte behövs och på så sätt optimera aggregeringspipelinen.

Med de två tidigare samlingarna kan du kombinera $match och $lookup så här:

db.users.aggregate([
   {
      $match: {
         country: "USA"
      }
   },
   {
      $lookup: {
         from: "orders",
         localField: "_id",
         foreignField: "user_id",
         as: "orders"
      }
   }
])

$match används för att filtrera efter användare från USA. Resultatet från $match kombineras sedan med $lookup för att få orderdetaljerna för användare från USA. Resultatet av ovanstående operation visas nedan:

$projekt

$project är ett steg som används för att omforma dokument genom att ange vilka fält som ska inkluderas, exkluderas eller läggas till i dokument. Till exempel, om du bearbetar dokument med tio fält vardera, men endast fyra fält i dokumenten innehåller data som du behöver för din databehandling, kan du använda $project för att filtrera ut de fält du inte behöver.

Detta låter dig undvika att skicka onödig data till nästa steg i din aggregeringspipeline.

Vi kan kombinera $lookup och $project 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" }
      }
   }
])

Ovanstående kombinerar användar- och beställningssamlingarna med $lookup, sedan används $project för att endast visa namnet på varje användare och det belopp som varje användare har spenderat. $project används också för att ta bort _id-fältet från resultaten. Resultatet av ovanstående operation visas nedan:

$varva ner

$unwind är ett aggregeringssteg som används för att dekonstruera eller avveckla ett arrayfält som skapar nya dokument för varje element i arrayen. Detta är användbart om du vill köra lite aggregering på arrayfältvärdena.

Till exempel, i exemplet nedan, om du vill köra aggregering på hobbyområdet, kan du inte göra det eftersom det är en array. Däremot kan du använda lossa det med $unwind och sedan utföra aggregering på de resulterande dokumenten.

Genom att använda användar- och ordersamlingarna kan vi använda $lookup och $unwind tillsammans så här:

db.users.aggregate([
   {
      $lookup: {
         from: "orders",
         localField: "_id",
         foreignField: "user_id",
         as: "orders"
      }
   },
   {
      $unwind: "$orders"
   }
])

I koden ovan returnerar $lookup ett arrayfält som kallas order. $unwind används sedan för att avveckla arrayfältet. Resultatet av denna operation visas nedan: Lägg märke till att Alice dyker upp två gånger eftersom hon hade två beställningar.

Exempel på användningsfall för $lookup

När du utför databehandling är $lookup ett användbart verktyg. Till exempel kan du ha två samlingar som du vill gå med i baserat på fält på samlingarna som har liknande data. Ett enkelt $lookup-steg kan användas för att göra detta och lägga till ett nytt fält i de primära samlingarna, som innehåller dokument hämtade från en annan samling.

Tänker på användar- och ordersamlingarna som visas nedan:

De två samlingarna kan kombineras med $lookup för att ge resultatet som visas nedan:

$lookup kan också användas för att utföra mer komplexa joins. $lookup är inte bara begränsad till att gå med på två samlingar. Du kan implementera flera $lookup-steg för att utföra kopplingar på mer än två samlingar. Tänk på de tre samlingarna som visas nedan:

Vi kan använda koden nedan för att utföra en mer komplex sammanfogning över de tre samlingarna för att få alla beställningar som gjordes och även detaljer om de produkter som beställdes.

Koden nedan låter oss göra just det:

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 ovanstående operation visas nedan:

Slutsats

När du utför databearbetning som involverar flera samlingar kan $lookup vara användbar eftersom det låter dig sammanfoga data och dra slutsatser baserat på data som lagras i flera samlingar. Databehandling bygger sällan på bara en samling.

För att dra meningsfulla slutsatser från data är det ett viktigt steg att sammanfoga data över flera samlingar. Överväg därför att använda $lookup-stadiet i din MongoDB-aggregationspipeline för att låta dig bearbeta dina data bättre och dra meningsfulla insikter från rådata som lagras över samlingar.

Du kan också utforska några MongoDB-kommandon och frågor.