MongoDB Academy · Lektion

$group: aggregera och beräkna totaler

Ni grupperar dokument efter en nyckel och beräknar summor, medelvärden, antal och andra ackumulatorer med $group.

Lektion 3 av 413 steg

$group: aggregera och beräkna totaler är en gratis lektion i MongoDB Academy på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för MongoDB Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i MongoDB Academy innehåller totalt 4 lektioner.

Vad gör $group?

Steget $group slår ihop flera indatadokument till färre utdatadokument baserat på en grupperingsnyckel. Dokument som har samma nyckelvärde slås ihop till ett enda utdatadokument, och ackumulatoroperatorer beräknar aggregerade värden för varje grupp. Se det som MongoDBs motsvarighet till SQL-satsen GROUP BY kombinerad med aggregeringsfunktioner som SUM och COUNT.

// Count orders per user
db.orders.aggregate([
  { $group: {
    _id: '$userId',         // group by userId
    orderCount: { $sum: 1 }  // count each document as 1
  }}
]);
// Output: one doc per unique userId with their order count

Fältet _id i $group

Varje $group-steg kräver ett _id-fält som definierar grupperingsnyckeln. _id kan vara en fältreferens ('$field'), ett beräknat uttryck, ett objekt med flera fält (för sammansatt gruppering) eller null (för att aggregera hela samlingen till ett dokument). Värdet för _id i utdata är gruppnyckeln.

// Group by single field
{ $group: { _id: '$status' } }

// Group by multiple fields (compound key)
{ $group: { _id: { year: { $year: '$createdAt' }, status: '$status' } } }

// Group all documents into one (grand total)
{ $group: { _id: null, grandTotal: { $sum: '$amount' } } }

// Group by computed expression
{ $group: { _id: { $toLower: '$category' } } }

$sum: räkna och summera

$sum är den mest använda ackumulatorn. Ange 1 för att räkna dokument i varje grupp eller en fältreferens för att summera numeriska fältvärden. Du kan också ange ett uttryck som utvärderas till ett tal. $sum ignorerar icke-numeriska värden och saknade fält (de räknas som noll), vilket gör den säker att använda med valfria numeriska fält.

db.sales.aggregate([{
  $group: {
    _id: '$region',
    // Count documents in each group
    transactionCount: { $sum: 1 },
    // Sum the 'amount' field
    totalRevenue: { $sum: '$amount' },
    // Sum a computed expression
    totalWithTax: { $sum: { $multiply: ['$amount', 1.1] } }
  }
}]);

$avg, $min, $max

$avg beräknar det aritmetiska medelvärdet, $min hittar det minsta värdet och $max hittar det största värdet bland alla dokument i en grupp. Alla tre fungerar med numeriska värden och även med strängar och datum (för min/max). De ignorerar nullvärden och saknade fältvärden.

db.orders.aggregate([{
  $group: {
    _id: '$productId',
    avgRating: { $avg: '$rating' },          // average rating
    minPrice: { $min: '$price' },            // lowest price ever sold
    maxPrice: { $max: '$price' },            // highest price ever sold
    firstOrder: { $min: '$createdAt' },      // earliest date
    latestOrder: { $max: '$createdAt' }      // most recent date
  }
}]);

$count i $group

Även om du vanligtvis räknar genom att använda { $sum: 1 } i ett $group-steg erbjuder MongoDB även ett fristående $count-steg för att räkna det totala antalet dokument i strömmen. $count-steget genererar ett enda dokument med antalet under det fältnamn du anger. Det motsvarar ett $group med _id: null och $sum: 1.

// Count total published articles
db.articles.aggregate([
  { $match: { status: 'published' } },
  { $count: 'totalPublished' }  // emits { totalPublished: N }
]);

// Equivalent using $group:
db.articles.aggregate([
  { $match: { status: 'published' } },
  { $group: { _id: null, totalPublished: { $sum: 1 } } }
]);

Sammansatta grupperingsnycklar

För att gruppera efter flera fält samtidigt anger du ett objekt som värde för _id. Varje nyckel i objektet blir en del av den sammansatta gruppnyckeln. Utdatadokumenten har ett kapslat _id-objekt. Detta är standardmetoden för att skapa flerdimensionella aggregeringar som 'intäkt per region och månad'.

// Revenue breakdown by region AND year-month
db.sales.aggregate([
  { $group: {
    _id: {
      region: '$region',
      year: { $year: '$saleDate' },
      month: { $month: '$saleDate' }
    },
    revenue: { $sum: '$amount' },
    count: { $sum: 1 }
  }},
  { $sort: { '_id.year': 1, '_id.month': 1, '_id.region': 1 } }
]);
// Output: { _id: { region: 'EMEA', year: 2024, month: 3 }, revenue: 50000, count: 120 }

Samla värden i arrayer med $push

$push-ackumulatorn samlar alla värden från ett fält i de grupperade dokumenten i en array. Detta är användbart för att samla alla order-ID:n för en användare, alla taggar i en kategori eller alla användar-ID:n som köpt en produkt. Resultatarrayen kan innehålla dubbletter; använd i stället $addToSet för att samla unika värden.

// Collect all order IDs per user
db.orders.aggregate([{
  $group: {
    _id: '$userId',
    orderIds: { $push: '$_id' },         // all order IDs for this user
    amounts: { $push: '$amount' },       // all amounts
    // Collect whole sub-documents
    orderSummaries: {
      $push: { orderId: '$_id', amount: '$amount', status: '$status' }
    }
  }
}]);

Ackumulatorerna $first och $last

$first och $last returnerar det första respektive sista fältvärdet som påträffas per grupp, i den ordning dokumenten bearbetas. Eftersom MongoDB inte garanterar dokumentordningen om du inte sorterar först bör du lägga till ett $sort-steg före $group-steget för att göra $first/$last meningsfulla, till exempel för 'första beställningsdatumet per kund'.

// Most and least recent order per customer
db.orders.aggregate([
  { $sort: { createdAt: 1 } },  // sort BEFORE group for meaningful first/last
  { $group: {
    _id: '$customerId',
    firstOrder: { $first: '$createdAt' },
    firstOrderId: { $first: '$_id' },
    lastOrder: { $last: '$createdAt' },
    lastAmount: { $last: '$amount' }
  }}
]);

Gruppering efter beräknade uttryck

$group:s _id kan vara vilket uttryck som helst, inte bara en fältreferens. Du kan gruppera efter ett avkortat datum (år-vecka), en beräknad kategori, ett matematiskt intervall eller en delsträng av ett fält. På så sätt kan du skapa flexibla analytiska grupperingar utan att behöva förberäknade intervallfält i de lagrade dokumenten.

// Group orders by price bucket: 0-99, 100-499, 500+
db.orders.aggregate([{
  $group: {
    _id: {
      $switch: {
        branches: [
          { case: { $lt: ['$amount', 100] }, then: 'small' },
          { case: { $lt: ['$amount', 500] }, then: 'medium' }
        ],
        default: 'large'
      }
    },
    count: { $sum: 1 },
    totalRevenue: { $sum: '$amount' }
  }
}]);

Gruppering i två steg

Komplexa analyser kräver ofta två $group-steg i följd: det första grupperar på detaljnivå (till exempel per användare), och det andra grupperar resultaten från det första steget på en högre nivå (till exempel per region). Detta mönster med två steg undviker kapslade $group-uttryck och ger renare och mer lättbegripliga pipelines.

// Average orders per user, per region
db.orders.aggregate([
  // Stage 1: sum per user
  { $group: {
    _id: { userId: '$userId', region: '$region' },
    userOrderCount: { $sum: 1 }
  }},
  // Stage 2: average of those sums, per region
  { $group: {
    _id: '$_id.region',
    avgOrdersPerUser: { $avg: '$userOrderCount' },
    uniqueUsers: { $sum: 1 }
  }}
]);

$group-prestanda: inget index tillgängligt

Till skillnad från $match kan steget $group inte använda ett index – det måste bearbeta alla dokument som skickas till det. Därför är det avgörande att minska indatamängden med ett tidigt $match. För mycket stora datamängder där $group använder för mycket minne kan allowDiskUse: true anges för att skriva överflödig data till disk. Ett alternativ är att beräkna och lagra aggregerade värden i förväg (Computed Pattern), vilket undviker gruppering vid körning i tidskritiska flöden.

// Allow disk use for large aggregations
db.orders.aggregate(
  [
    { $match: { year: 2024 } },
    { $group: { _id: '$productId', revenue: { $sum: '$amount' } } },
    { $sort: { revenue: -1 } }
  ],
  { allowDiskUse: true }  // spill to disk if memory limit exceeded
);

Snabb kontroll

Testa er förståelse av steget $group i aggregeringspipelinen.

Sammanfattning av lektionen

I den här lektionen har ni lärt er att $group slår samman dokument utifrån en nyckel som definieras i fältet _id, att ackumulatorer som $sum, $avg, $min, $max, $push beräknar aggregerade värden per grupp och att gruppering i två steg möjliggör hierarkisk analys. Nästa steg är att utforska $sort, $limit och $skip för att ordna och paginera aggregeringsresultat.

Gratis att börja

Lär dig JavaScript med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”$group: aggregera och beräkna totaler” gratis?

Ja – hela texten till ”$group: aggregera och beräkna totaler” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i MongoDB Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i MongoDB Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”$group: aggregera och beräkna totaler”?

Ni grupperar dokument efter en nyckel och beräknar summor, medelvärden, antal och andra ackumulatorer med $group. Ni övar på MongoDB Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig MongoDB Academy?

Du behöver inga förkunskaper. Utbildningen i MongoDB Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”$group: aggregera och beräkna totaler”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här MongoDB Academy-lektionen?

Ja. Varje MongoDB Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Pipelinkoncept: steg, operatorer och uttryck
  2. $match och $project: filtrera och omforma
  3. $group: aggregera och beräkna totaler
  4. $sort, $limit och $skip i pipelinen
← Tillbaka till MongoDB Academy