MongoDB Academy · Lektion

$lookup: Sammenføjning af samlinger i pipelinen

De lærende vil udføre venstre ydre joins mellem samlinger ved hjælp af $lookup og forstå konsekvenserne for ydeevnen ved joins på tværs af samlinger.

Lektion 1 af 413 trin

$lookup: Sammenføjning af samlinger i pipelinen er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i MongoDB Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. MongoDB Academy-kurset indeholder 4 lektioner i alt.

Hvorfor $lookup findes

MongoDB er designet til at indlejre relaterede data, men nogle gange skal data ligge i separate samlinger – især i scenarier med mange-til-mange eller en-til-mange, hvor indlejring ville føre til ubegrænset vækst af dokumenter. Stadiet $lookup udfører en venstresidet ydre sammenføjning mellem den aktuelle samling (den 'venstre' side) og en anden samling (den 'højre' side), så du kan samle relaterede data på serversiden i en enkelt aggregeringspipeline.

Grundlæggende syntaks for $lookup

Den grundlæggende $lookup har fire obligatoriske felter: from (den samling, der skal sammenføjes), localField (feltet i inputdokumentet), foreignField (feltet i den sammenføjede samling) og as (navnet på arrayfeltet, der føjes til outputtet). Resultatet er et array, fordi ét dokument kan matche flere dokumenter i den sammenføjede samling.

// Join orders with their product details
db.orders.aggregate([
  { $lookup: {
    from: 'products',          // collection to join
    localField: 'productId',   // field in orders
    foreignField: '_id',       // field in products
    as: 'productDetails'       // output array field name
  }}
]);
// Each order now has a 'productDetails' array with matching products

Udfoldning af det sammenføjede array

Da $lookup altid opretter et array i feltet as, har du ofte brug for at flade det ud for at få direkte adgang til underfelter. Hvis du ved, at sammenføjningen er en-til-en (for eksempel ved sammenføjning via et unikt _id), kan du bruge $unwind umiddelbart efter $lookup til at flade arrayet ud til ét indlejret objekt. Vær opmærksom på, at $unwind fjerner dokumenter, der ikke har nogen match (et tomt array).

db.orders.aggregate([
  { $lookup: {
    from: 'products',
    localField: 'productId',
    foreignField: '_id',
    as: 'product'
  }},
  // Flatten: productDetails array -> productDetails object
  { $unwind: '$product' },
  // Now access product fields directly:
  { $project: { orderId: '$_id', amount: 1, 'product.name': 1, 'product.price': 1 } }
]);

$lookup som en venstresidet ydre sammenføjning

$lookup udfører en venstresidet ydre sammenføjning: Alle dokumenter fra den venstre samling (inputsamlingen) inkluderes i outputtet, også selvom der ikke er nogen matchende dokumenter i den højre samling (den fremmede samling). I så fald sættes feltet as til et tomt array. Det adskiller sig fra en indre sammenføjning, hvor venstre dokumenter uden match ville blive udeladt. Hvis du vil filtrere dokumenter uden match fra, kan du tilføje et $match efter $lookup.

db.orders.aggregate([
  { $lookup: {
    from: 'products',
    localField: 'productId',
    foreignField: '_id',
    as: 'product'
  }},
  // Simulate inner join: exclude orders with no matching product
  { $match: { product: { $ne: [] } } },
  // Or equivalently:
  { $match: { 'product.0': { $exists: true } } }
]);

Pipeline-baseret $lookup til komplekse sammenføjninger

Den avancerede form af $lookup bruger en pipeline-indstilling i stedet for simpel felttilpasning. Det gør det muligt at køre vilkårlige pipelinestadier på den sammenføjede samling før sammenføjningen. Du kan filtrere, projektere og beregne i den sammenføjede pipeline ved hjælp af $$let-variabler til at overføre værdier fra det overordnede dokument. Det muliggør komplekse betingede sammenføjninger og sammenføjninger med ulighedsbetingelser.

// Join only active discounts for each product
db.products.aggregate([
  { $lookup: {
    from: 'discounts',
    let: { productId: '$_id', price: '$price' },  // pass parent fields
    pipeline: [
      { $match: {
        $expr: {
          $and: [
            { $eq: ['$productId', '$$productId'] },  // use $$var
            { $eq: ['$active', true] }
          ]
        }
      }},
      { $project: { amount: 1, expiresAt: 1 } }
    ],
    as: 'activeDiscounts'
  }}
]);

Selvsammenføjning med $lookup

Du kan bruge $lookup til at sammenføje en samling med sig selv – for eksempel for at finde en brugers leder ved at slå lederens ID op i den samme brugersamling. Sæt from til det samme samlingsnavn som inputsamlingen. Selvsammenføjninger er nyttige til hierarkiske data, eller når et dokument refererer til et andet dokument i den samme samling.

// Self-join: attach manager details to each employee
db.employees.aggregate([
  { $lookup: {
    from: 'employees',     // same collection
    localField: 'managerId',
    foreignField: '_id',
    as: 'manager'
  }},
  { $unwind: { path: '$manager', preserveNullAndEmptyArrays: true } },
  { $project: {
    name: 1,
    department: 1,
    'manager.name': 1
  }}
]);

Ydeevneovervejelser for $lookup

$lookup kan være dyr, hvis den sammenføjede samling er stor og ikke har indeks. MongoDB opretter et midlertidigt indeks på det fremmede felt under sammenføjningen, hvis der ikke allerede findes et, men indekset gemmes ikke permanent. Hvis du gentagne gange udfører $lookup på det samme felt, bør du oprette et permanent indeks på feltet i den fremmede samling for at undgå denne ekstra omkostning ved hver forespørgsel.

// Ensure foreignField is indexed in the joined collection
// 'products' is the joined collection, '_id' is always indexed
// But for custom fields, index explicitly:
db.discounts.createIndex({ productId: 1, active: 1 });

// Now this $lookup is fast because productId is indexed
db.products.aggregate([{
  $lookup: {
    from: 'discounts',
    localField: '_id',
    foreignField: 'productId',  // indexed!
    as: 'discounts'
  }
}]);

Flere $lookup-stadier

Du kan kæde flere $lookup-stadier sammen for at sammenføje mere end to samlinger i en enkelt pipeline. Hvert $lookup føjer et nyt arrayfelt til dokumentstrømmen. Husk, at hver ekstra sammenføjning multiplicerer datamængden og beregningsomkostningen – undgå at sammenføje mere end 2-3 store samlinger i en enkelt pipeline. Hvis du opdager, at du udfører mange sammenføjninger, bør du overveje, om indlejring af nogle data ville forenkle skemaet.

db.orders.aggregate([
  // Join 1: product details
  { $lookup: { from: 'products', localField: 'productId', foreignField: '_id', as: 'product' } },
  { $unwind: '$product' },

  // Join 2: customer details
  { $lookup: { from: 'customers', localField: 'customerId', foreignField: '_id', as: 'customer' } },
  { $unwind: '$customer' },

  { $project: {
    _id: 1, amount: 1,
    'product.name': 1,
    'customer.email': 1
  }}
]);

Reduktion af $lookup-data med en underprojektion i pipelinen

I den pipeline-baserede form af $lookup kan du inkludere et $project-stadie inde i sammenføjningens pipeline for kun at hente de felter, du har brug for fra den sammenføjede samling. Det reducerer den datamængde, der overføres fra den sammenføjede samling, samt hukommelsesforbruget for resultatet af sammenføjningen. Sammenføj aldrig hele store dokumenter, hvis du kun har brug for to eller tre felter fra dem.

db.orders.aggregate([{
  $lookup: {
    from: 'products',
    let: { pid: '$productId' },
    pipeline: [
      { $match: { $expr: { $eq: ['$_id', '$$pid'] } } },
      // Only fetch name and imageUrl, not the full product document
      { $project: { _id: 0, name: 1, imageUrl: 1, price: 1 } }
    ],
    as: 'product'
  }
}]);

$lookup kontra indlejring: Afvejningen

Hver $lookup er en afvejning: Det giver dig fleksibilitet på forespørgselstidspunktet, men tilføjer latenstid sammenlignet med at læse indlejrede data i ét dokument. Brug $lookup, når de sammenføjede data ændres ofte, og du ønsker én sandhedskilde; når datarelationen er mange-til-mange; eller når indlejring ville føre til ubegrænset vækst af dokumenter. Brug indlejring, når læsninger forekommer ofte, og de relaterede data sjældent ændres uafhængigt.

// When to embed (avoid $lookup):
// - User profile with 2-3 addresses (bounded, read often together)
// { user: { name, email, addresses: [...] } }

// When to $lookup (use references):
// - Orders referencing products (products change, shared by many orders)
// { order: { productId: ObjectId(...), qty: 2 } }
// -> $lookup products on read

Kort sammenføjning med $lookup på arrays

$lookup håndterer også situationer, hvor localField er et array med ID'er. MongoDB udfører automatisk en sammenføjning med flere værdier: For hvert element i localField-arrayet slår den det matchende dokument op i den fremmede samling og samler alle resultaterne. Det gør det nemt at sammenføje en artikels tagIds-array med en tags-samling i ét trin.

// Post document: { title: '...', tagIds: [ObjectId1, ObjectId2] }
// Join all tag documents for a post's tagIds array:
db.posts.aggregate([{
  $lookup: {
    from: 'tags',
    localField: 'tagIds',  // this is an array!
    foreignField: '_id',
    as: 'tags'
  }
}]);
// tags array in output contains one doc per ObjectId in tagIds

Hurtigt tjek

Test din forståelse af $lookup i aggregeringspipelinjen.

Opsummering af lektionen

I denne lektion lærte du: $lookup udfører en venstre ydre join mellem to samlinger ved hjælp af matchende feltværdier, pipeline-formen af $lookup understøtter komplekse betingede joins med $$let-variabler, og indeksering af det fremmede felt forbedrer join-ydeevnen markant. Nu skal vi se på $unwind til dekonstruering af arrayfelter.

Gratis at komme i gang

Lær JavaScript med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “$lookup: Sammenføjning af samlinger i pipelinen” gratis?

Ja — hele teksten til “$lookup: Sammenføjning af samlinger i pipelinen” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af MongoDB Academy-kurset, skal du opgradere til CoddyKit PRO. MongoDB Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “$lookup: Sammenføjning af samlinger i pipelinen”?

De lærende vil udføre venstre ydre joins mellem samlinger ved hjælp af $lookup og forstå konsekvenserne for ydeevnen ved joins på tværs af samlinger. Du øver dig i MongoDB Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på MongoDB Academy?

Der kræves ingen tidligere erfaring. MongoDB Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “$lookup: Sammenføjning af samlinger i pipelinen”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne MongoDB Academy-lektion?

Ja. Alle MongoDB Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. $lookup: Sammenføjning af samlinger i pipelinen
  2. $unwind: Opdeling af arrayfelter
  3. $addFields, $replaceRoot og $mergeObjects
  4. $out og $merge: Skrivning af pipeline-resultater
← Tilbage til MongoDB Academy