MongoDB Academy · leksjon

$sort, $limit og $skip i pipelinen

Deltakerne vil sortere og paginere aggregeringsresultater og forstå optimaliseringsreglene for å flytte $match og $sort foran $group.

Leksjon 4 av 413 trinn

$sort, $limit og $skip i pipelinen er en gratis leksjon i MongoDB Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i MongoDB Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i MongoDB Academy inneholder totalt 4 leksjoner.

Oversikt: Sortering og paginering av resultater

Tre stadier i aggregeringspipen styrer rekkefølgen og mengden av resultater: $sort sorterer dokumenter etter ett eller flere felt, $limit tar bare de første N dokumentene, og $skip forkaster de første N dokumentene. Sammen implementerer de sortering og paginering. Hvor i pipen De plasserer dem, har stor betydning for ytelsen.

Stadiet $sort

Stadiet $sort sorterer dokumenter etter verdiene i ett eller flere felt. Bruk 1 for stigende rekkefølge og -1 for synkende rekkefølge. Når flere felt er angitt, sorteres dokumentene først etter det første feltet, deretter etter det andre feltet blant dokumenter med samme verdi, og så videre – akkurat som flernivåsortering i SQL eller MongoDBs find().sort().

// Sort by revenue descending, then alphabetically by name for ties
db.products.aggregate([
  { $group: { _id: '$category', revenue: { $sum: '$price' } } },
  { $sort: { revenue: -1, _id: 1 } }  // revenue desc, category name asc
]);

$sort og indeksbruk

Når $sort er det første stadiet i pipen (eller følger etter en $match som bruker en indeks), kan MongoDB bruke en indeks til å utføre sorteringen – og dermed unngå sortering i minnet. Når $sort kommer etter stadier som oppretter nye felt (som $group eller $project), er ingen indeks tilgjengelig, og MongoDB utfører sorteringen i minnet. Store sorteringer i minnet (>100 MB) krever allowDiskUse: true.

// Index-backed sort: $sort on indexed field before any transformation
db.orders.aggregate([
  { $match: { userId: 'u1' } },
  { $sort: { createdAt: -1 } }  // if createdAt is indexed, no in-memory sort
]);

// In-memory sort: $sort after $group (computed field, no index)
db.orders.aggregate([
  { $group: { _id: '$userId', total: { $sum: '$amount' } } },
  { $sort: { total: -1 } }  // in-memory: 'total' is a computed field
]);

Stadiet $limit

$limit sender bare de første N dokumentene videre og forkaster resten. Det er enkelt å bruke – angi et heltall som spesifiserer det maksimale antallet dokumenter som skal slippes gjennom. $limit plassert før kostbare stadier som $lookup reduserer kraftig antallet koblinger eller oppslag som utføres. Spør alltid: «Kan jeg begrense tidlig?»

// Top 10 best-selling products
db.orders.aggregate([
  { $group: { _id: '$productId', sold: { $sum: '$qty' } } },
  { $sort: { sold: -1 } },
  { $limit: 10 },  // only top 10 pass through
  // Only 10 lookups instead of thousands:
  { $lookup: { from: 'products', localField: '_id', foreignField: '_id', as: 'product' } }
]);

Stadiet $skip

$skip forkaster de første N dokumentene fra strømmen. Det tilsvarer offset-paginering i aggregeringer: Side 2 starter med skip 10 (forutsatt 10 elementer per side). $skip kommer alltid etter $sort for å gi konsistente resultater – hvis usorterte dokumenter hoppes over, blir sidene uforutsigbare. I likhet med SQL OFFSET er $skip tregt ved store forskyvninger, fordi MongoDB fortsatt må behandle alle dokumentene som hoppes over.

const PAGE = 2;
const PAGE_SIZE = 10;

db.articles.aggregate([
  { $match: { status: 'published' } },
  { $sort: { publishedAt: -1 } },
  { $skip: (PAGE - 1) * PAGE_SIZE },  // skip page 1's 10 docs
  { $limit: PAGE_SIZE }               // take page 2's 10 docs
]);

Optimalisering: Sammenslåing av $sort + $limit

MongoDBs aggregeringsoptimalisering oppdager når et $sort-stadium etterfølges umiddelbart av et $limit-stadium, og slår dem sammen til en top-N-sortering. I stedet for å sortere alle dokumentene og deretter forkaste de fleste, beholder MongoDB bare de N beste kandidatene i en prioritetskø under sorteringen. Dette bruker O(N) minne i stedet for O(total)-minne. Optimaliseringen skjer automatisk – De får den bare ved å skrive $sort etterfulgt av $limit.

// This pattern triggers the top-N sort optimisation
db.reviews.aggregate([
  { $match: { productId: 'p1' } },
  { $sort: { rating: -1, helpful: -1 } },  // sort
  { $limit: 5 }   // $sort + $limit merged into top-5 sort internally
]);
// MongoDB never sorts ALL reviews; it tracks only the best 5

Optimalisering: Omorganisering av $match og $sort

Aggregeringsoptimaliseringen flytter også automatisk et $match-stadium tidligere i pipen når det er trygt å gjøre det. Hvis for eksempel $sort kommer før $match på et felt som $sort ikke beregnet, flytter optimaliseringen $match foran $sort for å redusere antallet dokumenter som må sorteres. De kan se endringer fra optimaliseringen i resultatet fra explain().

// You write:
db.orders.aggregate([
  { $sort: { amount: -1 } },
  { $match: { status: 'completed' } }  // optimizer moves this BEFORE $sort
]);

// Optimized execution (equivalent to):
db.orders.aggregate([
  { $match: { status: 'completed' } },  // fewer docs to sort
  { $sort: { amount: -1 } }
]);

Kombinere alle fire: Et komplett listeendepunkt

Et realistisk API-endepunkt som viser produkter med filtre, sortering og paginering, kombinerer $match, $sort, $skip og $limit i riktig rekkefølge. Mønsteret er alltid: filtrer → sorter → hopp over → begrens. Denne rekkefølgen sikrer at MongoDB bruker indekser til både filtrering og, når det er mulig, sortering før unødvendige dokumenter forkastes.

async function getProducts({ category, sort = 'price', page = 1, pageSize = 20 }) {
  return db.products.aggregate([
    { $match: { category, inStock: true } },   // 1. filter
    { $sort: { [sort]: 1 } },                  // 2. sort
    { $skip: (page - 1) * pageSize },          // 3. offset
    { $limit: pageSize }                       // 4. take page
  ]).toArray();
}

Ytelsen til $skip ved dype forskyvninger

Det grunnleggende problemet med $skip er at MongoDB fortsatt må behandle og forkaste hvert dokument det hopper over. På side 1000 med 20 elementer per side forkaster MongoDB 19 980 dokumenter før 20 dokumenter returneres. Dette blir gradvis tregere jo lenger ut i resultatene De kommer. For offentlige søke- eller feed-API-er, der brukerne sjelden går lenger enn til side 5–10, fungerer offset-paginering fint. For hyppig bruk av dyp paginering er keyset-paginering nødvendig.

// Page 1000 is SLOW: MongoDB processes and discards 19,980 docs
db.posts.aggregate([
  { $sort: { createdAt: -1 } },
  { $skip: 19980 },  // 999 * 20
  { $limit: 20 }
]);

// Keyset pagination: always fast regardless of page depth
db.posts.aggregate([
  { $match: { createdAt: { $lt: lastSeenTimestamp } } },  // cursor
  { $sort: { createdAt: -1 } },
  { $limit: 20 }
]);

$sort-minnegrense og allowDiskUse

Et $sort i minnet i aggregeringspipen er som standard begrenset til 100 MB. Hvis sorteringen overskrider denne grensen, mislykkes pipen med feilen QueryExceededMemoryLimitNoDiskUseAllowed. Send { allowDiskUse: true } som det andre argumentet til aggregate() for å aktivere skriving til disk. Alternativt kan De bruke en tidlig $match eller en støtteindeks for å redusere størrelsen på inndataene til sorteringen.

// Enable disk use for large sorts
db.events.aggregate(
  [
    { $match: { year: 2024 } },
    { $sort: { timestamp: -1 } },
    { $group: { _id: '$userId', events: { $push: '$type' } } }
  ],
  { allowDiskUse: true }  // allows spilling to disk
);

Hente totalantallet sammen med resultatene

Et vanlig API-mønster er å returnere både de paginerte resultatene og totalantallet i én enkelt tur til databasen. Bruk $facet til å dele pipen i to parallelle grener: én for resultater med $skip/$limit og én for $count. Dette unngår to separate aggregeringskall og er mer effektivt enn å telle alle dokumentene separat.

db.products.aggregate([
  { $match: { category: 'electronics' } },
  { $sort: { price: 1 } },
  { $facet: {
    // Branch 1: paginated results
    data: [
      { $skip: 0 },
      { $limit: 20 }
    ],
    // Branch 2: total count
    total: [
      { $count: 'count' }
    ]
  }}
]);
// Output: { data: [...20 docs...], total: [{ count: 348 }] }

Hurtigsjekk

Test forståelsen Deres av $sort, $limit og $skip i aggregeringspipen.

Oppsummering av leksjonen

I denne leksjonen lærte De at: $sort sorterer dokumenter og drar nytte av indeksbruk når det plasseres tidlig, $limit tar de første N dokumentene og slås sammen med $sort til en effektiv top-N-sortering, og $skip implementerer offset-paginering, men blir tregere ved dype forskyvninger. Deretter skal vi se på avanserte aggregeringsstadier, blant annet $lookup for å koble sammen samlinger.

Gratis å komme i gang

Lær deg JavaScript med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «$sort, $limit og $skip i pipelinen» gratis?

Ja – hele teksten i «$sort, $limit og $skip i pipelinen» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av MongoDB Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i MongoDB Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «$sort, $limit og $skip i pipelinen»?

Deltakerne vil sortere og paginere aggregeringsresultater og forstå optimaliseringsreglene for å flytte $match og $sort foran $group. Du øver på MongoDB Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med MongoDB Academy?

Ingen tidligere erfaring er nødvendig. MongoDB Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «$sort, $limit og $skip i pipelinen»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne MongoDB Academy-leksjonen?

Ja. Alle MongoDB Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Pipeline-konsepter: Trinn, operatorer og uttrykk
  2. $match og $project: Filtrere og omforme
  3. $group: Aggregere og beregne totaler
  4. $sort, $limit og $skip i pipelinen
← Tilbake til MongoDB Academy