Akkumulatorerne $first, $last og $top/$bottom
De lærende vil vælge det første eller sidste dokument pr. gruppe og bruge de nyere akkumulatorer $top og $bottom til at vælge ud fra en sorteringsnøgle.
Akkumulatorerne $first, $last og $top/$bottom er en gratis MongoDB Academy-lektion på CoddyKit. Dette er lektion 3 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.
Valg af ét dokument pr. gruppe
Nogle gange skal en aggregering vælge ét repræsentativt dokument fra hver gruppe i stedet for at beregne en numerisk aggregering. MongoDB har flere akkumulatorer til dette: $first, $last samt de nyere akkumulatorer $top og $bottom. De har hver deres betydning for, hvilket dokument der vælges, og det rigtige valg påvirker både korrekthed og ydeevne.
$first: Hentning af værdien fra det tidligste dokument
$first returnerer værdien fra det første dokument, der mødes i gruppen. Da MongoDB ikke garanterer rækkefølgen, dokumenterne behandles i, inden for et $group, medmindre du først sorterer, giver $first kun mening, når du placerer et $sort-trin umiddelbart før $group. Dette mønster med to trin—sortér og gruppér—er den almindelige måde pålideligt at vælge det tidligste eller højest prioriterede element pr. gruppe.
db.orders.aggregate([
// Sort by date ascending so $first gets the oldest order
{ $sort: { createdAt: 1 } },
{
$group: {
_id: '$customerId',
firstOrderDate: { $first: '$createdAt' },
firstOrderAmount: { $first: '$amount' },
firstOrderId: { $first: '$_id' }
}
}
])$last: Hentning af værdien fra det seneste dokument
$last returnerer værdien fra det sidste dokument, der mødes i gruppen. Det giver igen kun mening sammen med et foregående $sort. Sortér stigende, og brug $last for at få den seneste værdi pr. gruppe. Sortér faldende, og brug $first for at opnå det samme resultat. Det mest almindelige anvendelsesområde er at finde hver brugers eller kundes seneste aktivitet.
db.loginEvents.aggregate([
// Sort ascending: $last will be the most recent event
{ $sort: { timestamp: 1 } },
{
$group: {
_id: '$userId',
lastLoginTime: { $last: '$timestamp' },
lastLoginIp: { $last: '$ipAddress' },
totalLogins: { $sum: 1 }
}
}
])Ydeevneomkostninger ved sortering før gruppering
Mønsteret med $sort før $group har en vigtig konsekvens for ydeevnen: Det forhindrer MongoDB i at flytte $group foran $sort under optimering af behandlingsforløbet. Hvis samlingen er stor, og du har et indeks på sorteringsfeltet, kan MongoDB bruge det til sorteringsfasen, men skal stadig sortere alle dokumenter før grupperingen. For meget store samlinger kan dette være dyrt. Akkumulatorerne $top og $bottom blev delvist introduceret for at afhjælpe denne begrænsning.
// Potentially expensive on large collections:
// MongoDB must sort ALL documents before grouping
db.events.aggregate([
{ $sort: { timestamp: -1 } }, // sorts entire collection
{
$group: {
_id: '$userId',
latestEvent: { $first: '$eventType' }
}
}
])$top: Valg efter sorteringsnøgle inden for en gruppe
$top, som blev introduceret i MongoDB 5.2, lader dig vælge det øverste dokument i hver gruppe ud fra en sorteringsspecifikation—uden et separat $sort-trin. Du angiver et sortBy-udtryk og et output-udtryk direkte i akkumulatoren. MongoDB evaluerer sorteringen pr. gruppe, hvilket kan være mere effektivt end først at sortere hele samlingen.
db.orders.aggregate([
{
$group: {
_id: '$customerId',
mostRecentOrder: {
$top: {
sortBy: { createdAt: -1 }, // highest date first
output: {
orderId: '$_id',
amount: '$amount',
date: '$createdAt'
}
}
}
}
}
])$bottom: Valg af det sidste efter sorteringsnøgle
$bottom er modstykket til $top—den returnerer det dokument, der ville ligge sidst efter sortering efter den angivne nøgle inden for hver gruppe. Brug $bottom med sortBy: { timestamp: 1 } for at få den tidligste hændelse pr. gruppe, eller brug $top med den modsatte sorteringsretning—begge tilgange er ækvivalente. Vælg den, der tydeligst udtrykker din hensigt.
db.gameScores.aggregate([
{
$group: {
_id: '$playerId',
highestScore: {
$top: {
sortBy: { score: -1 },
output: { score: '$score', level: '$level', date: '$date' }
}
},
lowestScore: {
$bottom: {
sortBy: { score: -1 },
output: { score: '$score', level: '$level', date: '$date' }
}
}
}
}
])$topN og $bottomN: Valg af flere elementer
MongoDB har også akkumulatorerne $topN og $bottomN, som returnerer et array med de øverste eller nederste N dokumenter pr. gruppe ud fra en sorteringsnøgle. Dette er nyttigt til forespørgsler af ranglistetypen, hvor du vil have de 3 højeste resultater pr. niveau eller de 5 seneste ordrer pr. kunde, alt sammen beregnet i ét $group-trin.
db.scores.aggregate([
{
$group: {
_id: '$gameId',
top3Players: {
$topN: {
n: 3,
sortBy: { score: -1 },
output: { playerId: '$playerId', score: '$score' }
}
}
}
}
])Valg mellem $first/$last og $top/$bottom
Brug $first/$last, når du allerede sorterer behandlingsforløbet af andre årsager og ønsker en enkel, velkendt API. Brug $top/$bottom, når du kun har brug for valget og vil undgå omkostningerne ved at sortere hele samlingen før $group. I praksis kan $top/$bottom med passende indekser være betydeligt hurtigere for store samlinger, fordi MongoDB muligvis kan optimere valget pr. gruppe mere effektivt.
// Prefer $top when no prior $sort is needed for other stages:
db.orders.aggregate([
{
$group: {
_id: '$region',
latestOrder: {
$top: { sortBy: { date: -1 }, output: { amount: '$amount', date: '$date' } }
}
}
}
]);
// Use $first when you are already sorting for other accumulators:
db.orders.aggregate([
{ $sort: { date: -1 } },
{
$group: {
_id: '$region',
latestDate: { $first: '$date' },
latestAmount: { $first: '$amount' },
allAmounts: { $push: '$amount' } // also needs sorted input
}
}
])Praktisk anvendelse: Seneste pris pr. produkt
Et klassisk anvendelsesområde fra den virkelige verden er at vedligeholde en samling med prishistorik og forespørge efter den senest gældende pris for hvert produkt. Ved at bruge $top med sortering efter dato i faldende rækkefølge bliver forespørgslen kort og effektiv. Resultatet er ét dokument pr. produkt med den aktuelle pris, uden at der er behov for en separat samling med 'aktuel pris'.
db.priceHistory.aggregate([
{
$group: {
_id: '$productId',
currentPrice: {
$top: {
sortBy: { effectiveDate: -1 },
output: {
price: '$price',
currency: '$currency',
effectiveDate: '$effectiveDate'
}
}
}
}
}
])Kombination af akkumulatorer i ét $group
Du kan frit kombinere $first, $last, $top, $bottom, $sum, $avg og $push i ét $group-trin. Hver akkumulator arbejder uafhængigt på dokumenterne i gruppen. Det lader dig beregne opsummerende statistikker samtidig med, at du vælger repræsentative dokumenter i ét effektivt aggregeringstrin, så flere gennemløb af data undgås.
db.transactions.aggregate([
{ $sort: { timestamp: 1 } },
{
$group: {
_id: '$accountId',
firstTransaction: { $first: '$timestamp' },
lastTransaction: { $last: '$timestamp' },
transactionCount: { $sum: 1 },
totalVolume: { $sum: '$amount' },
avgTransaction: { $avg: '$amount' },
largestTransaction: { $max: '$amount' }
}
}
])Bemærkninger om versionskompatibilitet
$first og $last har været tilgængelige siden de tidlige MongoDB-versioner. Akkumulatorerne $top og $bottom blev introduceret i MongoDB 5.2, og $topN/$bottomN blev også tilgængelige omkring samme tidspunkt. Hvis du bruger en ældre MongoDB-version (før 5.2), skal du falde tilbage på mønsteret $sort efterfulgt af $first/$last. Kontrollér versionen af din Atlas-klynge eller din selvhostede version, før du bruger nyere operatorer.
Hurtig kontrol
Test din forståelse af begreberne MongoDB og NoSQL-databaser fra denne lektion.
Opsummering af lektionen
I denne lektion lærte du: $first/$last vælger værdier fra det første/sidste dokument i en gruppe (kræver et foregående $sort), $top/$bottom (MongoDB 5.2+) vælger efter sorteringsnøgle inden for gruppen uden et separat $sort-trin, og $topN/$bottomN returnerer arrays med de øverste eller nederste N elementer pr. gruppe. Dernæst ser vi på vinduesfunktioner med $setWindowFields til løbende totaler og glidende gennemsnit.
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 “Akkumulatorerne $first, $last og $top/$bottom” gratis?
Ja — hele teksten til “Akkumulatorerne $first, $last og $top/$bottom” 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 “Akkumulatorerne $first, $last og $top/$bottom”?
De lærende vil vælge det første eller sidste dokument pr. gruppe og bruge de nyere akkumulatorer $top og $bottom til at vælge ud fra en sorteringsnøgle. 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 3 af 4.
Hvor lang tid tager lektionen “Akkumulatorerne $first, $last og $top/$bottom”?
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
- $sum, $avg, $min, $max: Numerisk aggregering
- $push og $addToSet: Opbygning af arrays i grupper
- Akkumulatorerne $first, $last og $top/$bottom
- Vinduesfunktioner med $setWindowFields