Aggregation
Aggregation lets you process a collection through a pipeline of stages (filter, group, sort, project, count, …) and get computed results instead of raw documents. The API is intentionally similar to MongoDB’s aggregation pipeline, but only a focused subset of stages is implemented.
Basic usage
const result = users.aggregate([
{ $match: { active: true } },
{ $group: { _id: '$role', total: { $sum: 1 } } },
{ $sort: { total: -1 } }
]);
console.log(result);
// → [ { _id: 'member', total: 42 }, { _id: 'admin', total: 3 }, … ]
Supported stages
$match
Filter documents using the same query language as find().
{ $match: { status: 'open', priority: { $in: ['high', 'critical'] } } }
$sort
Sort the current set of documents. Values are 1 (ascending) or -1 (descending).
{ $sort: { createdAt: -1, title: 1 } }
$limit
Keep only the first N documents.
{ $limit: 10 }
$skip
Skip the first N documents.
{ $skip: 20 }
$project
Keep only the listed fields (value 1 means include).
{ $project: { name: 1, email: 1, 'profile.city': 1 } }
$group
Group documents by a key and compute accumulators.
The group key is given by _id (use a field name with a leading $,
or null to put everything in one group).
Supported accumulators:
$sum– sum a field, or use1to count documents$avg– average of a numeric field$min– minimum value$max– maximum value$push– collect values into an array
// Count users per role
users.aggregate([
{ $group: { _id: '$role', count: { $sum: 1 } } }
]);
// Average age and list of names per city
users.aggregate([
{ $group: {
_id: '$profile.city',
avgAge: { $avg: '$age' },
names: { $push: '$name' }
}}
]);
// Single global total
orders.aggregate([
{ $group: { _id: null, revenue: { $sum: '$total' } } }
]);
$count
Replace the pipeline result with a single document that contains the count.
users.aggregate([
{ $match: { active: true } },
{ $count: 'activeUsers' }
]);
// → [ { activeUsers: 128 } ]
Pipeline order matters
Stages are applied from top to bottom. A typical useful order is:
$match– reduce the set early$group– aggregate$sort– order the groups$limit/$skip– pagination$project– shape the final output
Real-world example – sales dashboard
const orders = db.collection({ name: 'orders', autoId: true });
// Top 5 products by revenue this month
const topProducts = orders.aggregate([
{ $match: {
status: 'paid',
createdAt: { $gte: '2026-10-01' }
}},
{ $group: {
_id: '$productId',
revenue: { $sum: '$total' },
units: { $sum: '$quantity' }
}},
{ $sort: { revenue: -1 } },
{ $limit: 5 }
]);
console.log(topProducts);
$match early,
or use ordinary find + application-level processing.