$match og $project: Filtrering og omformning
De lærende vil placere $match tidligt i pipelinen af hensyn til ydeevnen og bruge $project til at omdøbe felter og beregne nye felter.
$match og $project: Filtrering og omformning er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 2 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.
Trinnet $match
Trinnet $match svarer i en aggregeringspipeline til et find()-filter. Det accepterer den samme forespørgselssyntaks – lighedstjek, sammenligningsoperatorer, logiske operatorer, $regex og $elemMatch – og filtrerer dokumentstrømmen ved at fjerne dokumenter, der ikke matcher. Dokumenter, der slipper igennem, sendes videre til næste trin, mens resten kasseres.
// $match uses the same syntax as find() filters
db.orders.aggregate([
{ $match: {
status: 'completed',
amount: { $gte: 100 },
createdAt: { $gte: new Date('2024-01-01') }
}}
]);
// Only orders matching ALL three conditions pass throughPlacér $match først for at bruge indeks
Når $match er det første trin i pipelinen, kan MongoDB bruge et indeks til at udføre filteret – præcis som ved en find()-forespørgsel. Hvis $match kommer efter andre trin, går fordelen ved indekset tabt, fordi forespørgselsplanlæggeren kun flytter indeksbrug til det første trin. Dette er den vigtigste regel for ydeevne ved design af aggregeringspipelines.
// GOOD: $match first -> uses index on userId
db.orders.aggregate([
{ $match: { userId: 'u1', status: 'active' } }, // index used here
{ $group: { _id: '$productId', count: { $sum: 1 } } }
]);
// BAD: $match after $group -> full collection scan
db.orders.aggregate([
{ $group: { _id: '$productId', count: { $sum: 1 } } },
{ $match: { userId: 'u1' } } // too late for index
]);Brug af $match med $text
Operatoren $text til fuldtekstsøgning kan kun bruges i $match og kun, når det er det første pipeline-trin. Begrænsningen findes, fordi MongoDB skal sende tekstsøgningen til tekstindekset, hvilket sker på forespørgselsplanniveauet, før nogen trintransformeringer udføres. Efter at $match har filtreret efter tekst, kan du projicere tekstscoren og sortere efter relevans i efterfølgende trin.
db.articles.aggregate([
// $text in $match MUST be the first stage
{ $match: { $text: { $search: 'mongodb aggregation' } } },
{ $addFields: { score: { $meta: 'textScore' } } },
{ $sort: { score: -1 } },
{ $limit: 5 }
]);Trinnet $project
Trinnet $project omformer dokumenter: du kan inkludere eller udelukke felter, omdøbe felter og beregne helt nye felter ved hjælp af udtryksoperatorer. Det sender ét outputdokument videre for hvert inputdokument (i modsætning til $group, som samler mange dokumenter i ét). Et $project-trin bruges ofte til at gøre dokumenter mindre før ressourcekrævende trin eller til at forberede den endelige outputstruktur.
db.users.aggregate([
{ $project: {
_id: 0, // exclude _id
name: 1, // include name
email: 1, // include email
// Exclude password - never send to client!
// (fields not listed are excluded when any field is included)
}}
]);Inkludering kontra udelukkelse i $project
Ligesom projektioner i find() kan $project ikke blande inkludering og udelukkelse i samme trin – med undtagelse af _id, som altid udtrykkeligt kan udelukkes, selv i en inkluderende projektion. Sæt et felt til 1 for at inkludere det, 0 for at udelukke det eller et udtryk for at beregne og inkludere det. Felter, der ikke nævnes i en inkluderende projektion, fjernes.
// Inclusion mode: list what you WANT
db.products.aggregate([{
$project: {
_id: 0, // OK to exclude _id in inclusion mode
name: 1,
price: 1
}
}]);
// Exclusion mode: list what you DON'T want
db.products.aggregate([{
$project: {
password: 0,
__v: 0
}
}]);
// Cannot mix: { name: 1, password: 0 } is an error (except _id)Beregning af nye felter i $project
Den egentlige styrke ved $project er beregningen af nye afledte felter ved hjælp af udtryksoperatorer. Du kan omdøbe et felt ved at tildele det en felthenvisning, udføre aritmetik, formatere strenge eller bruge betingelser – alt sammen på serversiden uden at røre de gemte dokumenter. De beregnede felter findes kun i pipeline-outputtet; de underliggende dokumenter ændres ikke.
db.invoices.aggregate([
{ $project: {
invoiceNumber: '$_id', // rename _id to invoiceNumber
clientName: '$client.name', // flatten nested field
subtotal: 1,
tax: { $multiply: ['$subtotal', 0.08] }, // compute tax
total: { $add: ['$subtotal', { $multiply: ['$subtotal', 0.08] }] },
issued: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } }
}}
]);Omdøbning og indlejring af felter
Du kan bruge $project til at omstrukturere dokumentets form: udjævn indlejrede felter til øverste niveau, eller saml flade felter i et indlejret underdokument. Det er nyttigt, når MongoDB-outputtet skal følge et API-svarskema, der adskiller sig fra strukturen i det gemte dokument, uden at du ændrer måden, dataene gemmes på.
// Document: { firstName: 'Alice', lastName: 'Smith', age: 30 }
// API wants: { name: { first, last }, age }
db.users.aggregate([{
$project: {
_id: 0,
name: {
first: '$firstName', // group into nested object
last: '$lastName'
},
age: 1
}
}]);
// Output: { name: { first: 'Alice', last: 'Smith' }, age: 30 }Brug af $project med arrays
$project understøtter arrayudtryk til at transformere eller filtrere arrays i dokumenter. Du kan bruge $map til at transformere hvert element, $filter til at vælge elementer, der matcher en betingelse, $slice til at udtage en delmængde eller $arrayElemAt til at tilgå et bestemt indeks. Disse operationer kører på serversiden på hele arrayet uden behov for flere pipelinetrin.
db.articles.aggregate([{
$project: {
title: 1,
// Keep only published tags
activeTags: {
$filter: {
input: '$tags',
as: 'tag',
cond: { $eq: ['$$tag.active', true] }
}
},
// First author only
leadAuthor: { $arrayElemAt: ['$authors', 0] },
// Uppercase each tag name
upperTags: { $map: { input: '$tags', as: 't', in: { $toUpper: '$$t' } } }
}
}]);Flere $match-trin
Du kan bruge flere $match-trin i den samme pipeline. Et almindeligt mønster er at bruge $match tidligt for at udnytte et indeks, derefter bruge $group eller $project til at beregne nye felter og så bruge et andet $match til at filtrere efter de beregnede værdier. Det første $match får fordel af indeksbrug; det andet filtrerer det beregnede resultatsæt.
db.orders.aggregate([
// First $match: uses index on userId
{ $match: { userId: 'u1' } },
// Compute revenue per product
{ $group: { _id: '$productId', revenue: { $sum: '$amount' } } },
// Second $match: filter computed revenue (no index possible here)
{ $match: { revenue: { $gte: 500 } } },
{ $sort: { revenue: -1 } }
]);Hvornår skal du bruge $addFields i stedet for $project
En almindelig frustration ved $project er, at du i inkluderingstilstand skal angive hvert felt, du vil beholde. Hvis du blot vil tilføje nye felter uden at fjerne eksisterende felter, skal du i stedet bruge $addFields (eller dets alias $set). $addFields fører alle eksisterende felter videre og tilføjer eller overskriver kun de angivne felter – langt mindre omstændeligt ved enkle tilføjelser af beregnede felter.
// $project: must list ALL fields you want to keep
db.users.aggregate([{ $project: { name: 1, email: 1, age: 1,
ageGroup: { $cond: { if: { $lt: ['$age', 18] }, then: 'minor', else: 'adult' } }
}}]);
// $addFields: keeps all fields, just adds ageGroup
db.users.aggregate([{ $addFields: {
ageGroup: { $cond: { if: { $lt: ['$age', 18] }, then: 'minor', else: 'adult' } }
}}]);
// All original fields (name, email, age, etc.) are preservedPipeline-ydeevne: $project tidligt
Hvis du placerer et $project-trin tidligt i pipelinen for at fjerne unødvendige felter, reducerer du den hukommelse og båndbredde, som efterfølgende trin bruger. Hvis senere trin ikke har brug for et stort indlejret array eller et langt tekstfelt, kan du udelukke dem med et tidligt $project- eller $unset-trin. Det har især stor betydning, når dokumenterne er store, og pipelinen har mange trin.
db.articles.aggregate([
{ $match: { status: 'published' } },
// Trim large fields early before expensive stages
{ $project: {
title: 1,
authorId: 1,
publishedAt: 1,
categoryId: 1,
// Exclude: body (could be 50KB), rawHtml (100KB)
// This reduces memory in all subsequent stages
}},
{ $lookup: { from: 'authors', localField: 'authorId', foreignField: '_id', as: 'author' } },
{ $sort: { publishedAt: -1 } },
{ $limit: 20 }
]);Hurtigt tjek
Test din forståelse af $match og $project i aggregeringspipelinen.
Opsummering af lektionen
I denne lektion har du lært, at $match filtrerer dokumentstrømmen ved hjælp af den samme forespørgselssyntaks som find() og bør placeres først for at udnytte indeks, at $project omformer dokumenter ved at inkludere, udelukke og beregne felter, og at $addFields er bedre, når du blot vil tilføje felter uden at angive alle eksisterende felter. Nu tager vi fat på $group til aggregering og beregning af totaler.
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 “$match og $project: Filtrering og omformning” gratis?
Ja — hele teksten til “$match og $project: Filtrering og omformning” 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 “$match og $project: Filtrering og omformning”?
De lærende vil placere $match tidligt i pipelinen af hensyn til ydeevnen og bruge $project til at omdøbe felter og beregne nye felter. 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 2 af 4.
Hvor lang tid tager lektionen “$match og $project: Filtrering og omformning”?
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
- Pipelinekoncepter: trin, operatorer og udtryk
- $match og $project: Filtrering og omformning
- $group: Samling og beregning af totaler
- $sort, $limit og $skip i pipelinen