Aggregation in MongoDB is used to process documents and calculate useful results. It can filter records, group documents, calculate totals, sort results, and generate reports.
For example, a coaching institute can use aggregation to calculate total student fees, count students in each course, and find the average marks of students.
Aggregation processes a collection of documents and produces results based on the operations we specify.
Consider these student documents:
{
name: "Rahul",
course: "Java",
fee: 5000
}
{
name: "Priya",
course: "Python",
fee: 6000
}
{
name: "Aman",
course: "Java",
fee: 4500
}
Using aggregation, we can calculate:
MongoDB provides the aggregate() method
to run an aggregation pipeline.
db.collection.aggregate([
{ stage1 },
{ stage2 },
{ stage3 }
])
The pipeline contains stages. Each stage performs an operation on the documents and passes its results to the next stage.
db.students.aggregate([
{
$match: {
course: "Java"
}
}
])
The $match stage returns documents
whose course is Java.
An aggregation pipeline is a sequence of stages. The output of one stage becomes the input of the next stage.
db.students.aggregate([
{
$match: {
course: "Java"
}
},
{
$sort: {
fee: -1
}
},
{
$limit: 5
}
])
This pipeline performs three operations:
$match selects Java students.$sort sorts them by fee from highest to lowest.$limit returns up to five matching documents.
The $match stage filters documents
according to a specified condition.
db.students.aggregate([
{
$match: {
course: "Java"
}
}
])
db.students.aggregate([
{
$match: {
fee: { $gt: 5000 }
}
}
])
The second pipeline returns only documents where the fee is greater than 5000.
The $group stage groups documents
using a specified key. It can also calculate totals,
counts, averages, minimums, and maximums.
db.students.aggregate([
{
$group: {
_id: "$course",
totalStudents: {
$sum: 1
}
}
}
])
Here, _id: "$course" groups documents
by course. The expression $sum: 1
counts each document in its group.
Example output:
{
_id: "Java",
totalStudents: 2
}
{
_id: "Python",
totalStudents: 1
}
The exact order of the returned groups is not guaranteed unless you add a sorting stage.
The $sum accumulator calculates a sum
inside a group.
db.students.aggregate([
{
$group: {
_id: null,
totalFees: {
$sum: "$fee"
}
}
}
])
The expression _id: null places all
input documents into one group. The sum of their
fee values is returned as totalFees.
For the sample documents, the total is 15500.
db.students.aggregate([
{
$group: {
_id: null,
totalStudents: {
$sum: 1
}
}
}
])
This returns the number of documents in the input collection that reach the group stage.
The $avg accumulator calculates the
average of numeric values.
db.students.aggregate([
{
$group: {
_id: null,
averageFee: {
$avg: "$fee"
}
}
}
])
For the sample fees of 5000, 6000, and 4500, the average is approximately 5166.67.
db.students.aggregate([
{
$group: {
_id: "$course",
averageFee: {
$avg: "$fee"
}
}
}
])
This calculates a separate average fee for each course.
The $sort stage arranges documents
in ascending or descending order.
db.students.aggregate([
{
$sort: {
fee: 1
}
}
])
db.students.aggregate([
{
$sort: {
fee: -1
}
}
])
Use 1 for ascending order and
-1 for descending order.
The $project stage selects fields,
excludes fields, or creates calculated fields
in the pipeline output.
db.students.aggregate([
{
$project: {
_id: 0,
name: 1,
course: 1
}
}
])
This output contains only the name and course fields.
db.students.aggregate([
{
$project: {
_id: 0,
name: 1,
fee: 1,
feeCategory: {
$cond: [
{ $gte: ["$fee", 5000] },
"High",
"Standard"
]
}
}
}
])
The $cond expression creates a
calculated field named feeCategory.
Fees of 5000 or more are categorized as High;
other fees are categorized as Standard.
Aggregation pipelines provide $limit
and $skip stages for controlling
the number of documents returned.
db.students.aggregate([
{
$limit: 3
}
])
db.students.aggregate([
{
$skip: 2
}
])
db.students.aggregate([
{
$sort: {
fee: -1
}
},
{
$limit: 2
}
])
Sorting before limiting makes the result useful when selecting the highest or lowest values.
The following pipeline finds Java students, groups them by course, counts students, and calculates their total fees.
db.students.aggregate([
{
$match: {
course: "Java"
}
},
{
$group: {
_id: "$course",
totalStudents: {
$sum: 1
},
totalFees: {
$sum: "$fee"
},
averageFee: {
$avg: "$fee"
}
}
},
{
$project: {
_id: 0,
course: "$_id",
totalStudents: 1,
totalFees: 1,
averageFee: 1
}
}
])
This pipeline performs four tasks:
$match.$group.$project.aggregate() runs an aggregation pipeline.$match filters documents.$group groups documents and calculates results.$sum calculates totals or counts when used with 1.$avg calculates the average of numeric values.$sort sorts pipeline results.$project selects or calculates output fields.$limit limits the number of documents.$skip skips a specified number of documents.
Create a collection named
practice_aggregation and insert these documents:
db.practice_aggregation.insertMany([
{
_id: 1,
name: "Rahul",
course: "Java",
fee: 5000,
marks: 80
},
{
_id: 2,
name: "Priya",
course: "Python",
fee: 6000,
marks: 90
},
{
_id: 3,
name: "Aman",
course: "Java",
fee: 4500,
marks: 75
},
{
_id: 4,
name: "Neha",
course: "Python",
fee: 7000,
marks: 95
},
{
_id: 5,
name: "Karan",
course: "Java",
fee: 5500,
marks: 85
}
])
$match.$group.$project.Run the insertion command only once, or clear the test collection before inserting the same sample data again.
1. Which method runs an aggregation pipeline?
2. Which stage groups documents?
3. Which accumulator calculates an average?