$first-, $last- und $top/$bottom-Aggregatfunktionen
Sie wählen das erste oder letzte Dokument pro Gruppe aus und verwenden die neueren Aggregatfunktionen $top und $bottom, um anhand eines Sortierschlüssels auszuwählen.
$first-, $last- und $top/$bottom-Aggregatfunktionen ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des MongoDB Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.
Ein Dokument pro Gruppe auswählen
Manchmal muss eine Aggregation ein einzelnes repräsentatives Dokument aus jeder Gruppe auswählen, anstatt einen numerischen Aggregatwert zu berechnen. MongoDB stellt dafür mehrere Akkumulatoren bereit: $first, $last sowie die neueren Akkumulatoren $top und $bottom. Jeder hat eine eigene Semantik dafür, welches Dokument ausgewählt wird. Die richtige Wahl wirkt sich sowohl auf die Korrektheit als auch auf die Performance aus.
$first: Den Wert des frühesten Dokuments übernehmen
$first gibt den Wert aus dem ersten Dokument zurück, das innerhalb der Gruppe verarbeitet wird. Da MongoDB innerhalb eines $group keine Verarbeitungsreihenfolge garantiert, sofern Sie nicht vorher sortieren, ist $first nur sinnvoll, wenn Sie unmittelbar vor $group eine $sort-Phase platzieren. Dieses zweistufige Muster – zuerst sortieren, dann gruppieren – ist die Standardmethode, um zuverlässig das früheste oder höchstpriorisierte Element pro Gruppe auszuwählen.
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: Den Wert des neuesten Dokuments übernehmen
$last gibt den Wert aus dem letzten Dokument zurück, das innerhalb der Gruppe verarbeitet wird. Auch dies ist nur in Verbindung mit einer vorhergehenden $sort-Phase sinnvoll. Sortieren Sie aufsteigend und verwenden Sie $last, um den neuesten Wert pro Gruppe zu erhalten. Sortieren Sie absteigend und verwenden Sie $first, um dasselbe Ergebnis zu erzielen. Ein besonders häufiger Anwendungsfall ist das Ermitteln der letzten Aktivität jedes Benutzers oder Kunden.
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 }
}
}
])Performancekosten der Sortierung vor der Gruppierung
Das Muster $sort vor $group hat eine wichtige Auswirkung auf die Performance: Es verhindert, dass MongoDB $group während der Pipeline-Optimierung vor $sort verschiebt. Wenn die Collection groß ist und Sie über einen Index für das Sortierfeld verfügen, kann MongoDB diesen für die Sortierphase verwenden, muss aber trotzdem alle Dokumente vor der Gruppierung sortieren. Bei sehr großen Collections kann dies kostspielig sein. Die Akkumulatoren $top und $bottom wurden unter anderem eingeführt, um diese Einschränkung zu beheben.
// 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: Nach Sortierschlüssel innerhalb einer Gruppe auswählen
Mit $top, das in MongoDB 5.2 eingeführt wurde, können Sie das oberste Dokument innerhalb jeder Gruppe anhand einer Sortierspezifikation auswählen – ohne eine separate $sort-Phase. Sie geben einen sortBy-Ausdruck und einen output-Ausdruck direkt im Akkumulator an. MongoDB wertet die Sortierung pro Gruppe aus, was effizienter sein kann, als zunächst die gesamte Collection zu sortieren.
db.orders.aggregate([
{
$group: {
_id: '$customerId',
mostRecentOrder: {
$top: {
sortBy: { createdAt: -1 }, // highest date first
output: {
orderId: '$_id',
amount: '$amount',
date: '$createdAt'
}
}
}
}
}
])$bottom: Das letzte Dokument nach Sortierschlüssel auswählen
$bottom ist das Gegenstück zu $top – der Akkumulator gibt das Dokument zurück, das nach der Sortierung anhand des angegebenen Schlüssels innerhalb der jeweiligen Gruppe an letzter Stelle stehen würde. Verwenden Sie $bottom mit sortBy: { timestamp: 1 }, um das früheste Ereignis pro Gruppe zu erhalten, oder $top mit der entgegengesetzten Sortierrichtung – beide Ansätze sind gleichwertig. Wählen Sie den Ansatz, der Ihre Absicht klarer ausdrückt.
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 und $bottomN: Mehrere Elemente auswählen
MongoDB stellt außerdem die Akkumulatoren $topN und $bottomN bereit. Sie geben anhand eines Sortierschlüssels ein Array mit den obersten oder untersten N Dokumenten pro Gruppe zurück. Dies ist für Abfragen im Stil von Bestenlisten nützlich, etwa wenn Sie die drei höchsten Punktzahlen pro Level oder die fünf neuesten Bestellungen pro Kunde benötigen – alles berechnet in einer einzigen $group-Phase.
db.scores.aggregate([
{
$group: {
_id: '$gameId',
top3Players: {
$topN: {
n: 3,
sortBy: { score: -1 },
output: { playerId: '$playerId', score: '$score' }
}
}
}
}
])Zwischen $first/$last und $top/$bottom wählen
Verwenden Sie $first/$last, wenn Sie die Pipeline bereits aus anderen Gründen sortieren und eine einfache, vertraute API nutzen möchten. Verwenden Sie $top/$bottom, wenn Sie nur die Auswahlfunktion benötigen und die Kosten einer vollständigen Sortierung der Collection vor $group vermeiden möchten. In der Praxis können $top/$bottom mit geeigneten Indizes bei großen Collections deutlich schneller sein, da MongoDB die Auswahl pro Gruppe möglicherweise effizienter optimieren kann.
// 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
}
}
])Praxisnaher Anwendungsfall: Aktueller Preis pro Produkt
Ein klassischer Anwendungsfall aus der Praxis ist die Pflege einer Collection mit einer Preis-Historie und die Abfrage des zuletzt gültigen Preises für jedes Produkt. Mit $top und einer Sortierung nach Datum in absteigender Reihenfolge lässt sich diese Abfrage kompakt und effizient formulieren. Das Ergebnis enthält ein Dokument pro Produkt mit dem aktuellen Preis, ohne dass eine separate Collection für aktuelle Preise erforderlich ist.
db.priceHistory.aggregate([
{
$group: {
_id: '$productId',
currentPrice: {
$top: {
sortBy: { effectiveDate: -1 },
output: {
price: '$price',
currency: '$currency',
effectiveDate: '$effectiveDate'
}
}
}
}
}
])Akkumulatoren in einer einzigen $group-Phase kombinieren
Sie können $first, $last, $top, $bottom, $sum, $avg und $push problemlos in einer einzigen $group-Phase kombinieren. Jeder Akkumulator arbeitet unabhängig mit den Dokumenten der Gruppe. Dadurch können Sie zusammen mit der Auswahl repräsentativer Dokumente auch zusammenfassende Statistiken in einer effizienten Aggregationsphase berechnen und mehrere Durchläufe über die Daten vermeiden.
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' }
}
}
])Hinweise zur Versionskompatibilität
$first und $last sind seit frühen MongoDB-Versionen verfügbar. Die Akkumulatoren $top und $bottom wurden in MongoDB 5.2 eingeführt; auch $topN/$bottomN wurden ungefähr zu diesem Zeitpunkt verfügbar. Wenn Sie eine ältere MongoDB-Version verwenden (vor 5.2), greifen Sie auf das Muster $sort gefolgt von $first/$last zurück. Prüfen Sie vor der Verwendung neuerer Operatoren die Version Ihres Atlas-Clusters oder Ihrer selbst gehosteten Instanz.
Kurze Überprüfung
Testen Sie Ihr Verständnis der Konzepte zu MongoDB & NoSQL Databases aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: $first/$last wählen Werte aus dem ersten/letzten Dokument einer Gruppe aus (erfordern eine vorherige $sort-Phase), $top/$bottom (MongoDB 5.2+) wählen anhand eines Sortierschlüssels innerhalb der Gruppe aus, ohne eine separate $sort-Phase und $topN/$bottomN geben Arrays mit den obersten oder untersten N Elementen pro Gruppe zurück. Als Nächstes sehen wir uns mit $setWindowFields Fensterfunktionen für laufende Summen und gleitende Durchschnitte an.
Lerne JavaScript mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 30
- Lektionen
- 120
Häufig gestellte Fragen
Ist die Lektion „$first-, $last- und $top/$bottom-Aggregatfunktionen“ kostenlos?
Ja — der vollständige Text von „$first-, $last- und $top/$bottom-Aggregatfunktionen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des MongoDB Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „$first-, $last- und $top/$bottom-Aggregatfunktionen“?
Sie wählen das erste oder letzte Dokument pro Gruppe aus und verwenden die neueren Aggregatfunktionen $top und $bottom, um anhand eines Sortierschlüssels auszuwählen. Du übst MongoDB Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um MongoDB Academy zu starten?
Keine Vorkenntnisse erforderlich. MongoDB Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „$first-, $last- und $top/$bottom-Aggregatfunktionen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser MongoDB Academy-Lektion Code schreiben und ausführen?
Ja. Jede MongoDB Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- $sum, $avg, $min, $max: Numerische Aggregation
- $push und $addToSet: Arrays in Gruppen erstellen
- $first-, $last- und $top/$bottom-Aggregatfunktionen
- Fensterfunktionen mit $setWindowFields