Overview
These methods provide advanced aggregation capabilities: percentile() for statistical analysis and aggregate() for direct access to MongoDB’s aggregation pipeline.
percentile()
Calculates the nth percentile of values for a specified numeric field. Useful for understanding data distribution and performance metrics.
Signature
static async percentile<T extends BaseModel, K extends keyof T>(
this: ObjectType<T>,
key: K,
n: number
): Promise<number>
Parameters
The field name to calculate the percentile for. Must be a numeric field.
The percentile to calculate (0-100). Common values: 50 (median), 95 (p95), 99 (p99).
Returns
The value at the specified percentile. Returns 0 if no documents match.
Examples
// Calculate median response time (50th percentile)
const median = await ResponseTime.percentile('value', 50)
console.log(`Median response time: ${median}ms`)
// Calculate p95 (95th percentile) - common SLA metric
const p95 = await ResponseTime.percentile('value', 95)
console.log(`95% of requests complete within: ${p95}ms`)
// Calculate p99 for high-precision monitoring
const p99 = await ResponseTime.percentile('value', 99)
// Percentile with filters
const apiP95 = await ResponseTime
.where('endpoint', '/api/users')
.percentile('duration', 95)
Common Percentile Values
// Performance monitoring dashboard
const metrics = await ApiMetric.where('date', today)
const p50 = await metrics.percentile('responseTime', 50) // Median
const p90 = await metrics.percentile('responseTime', 90) // 90th percentile
const p95 = await metrics.percentile('responseTime', 95) // 95th percentile
const p99 = await metrics.percentile('responseTime', 99) // 99th percentile
console.log('Response Time Percentiles:')
console.log(`p50: ${p50}ms`)
console.log(`p90: ${p90}ms`)
console.log(`p95: ${p95}ms`)
console.log(`p99: ${p99}ms`)
aggregate()
Provides direct access to MongoDB’s powerful aggregation pipeline for complex data transformations and analysis.
Signature
static async aggregate<T extends BaseModel>(
this: ObjectType<T>,
stages: Record<string, unknown>[]
): Promise<any[]>
Parameters
stages
Record<string, unknown>[]
required
An array of MongoDB aggregation pipeline stages. Each stage is an object with a single operator key.
Returns
Array of aggregation results. The structure depends on your pipeline stages.
Examples
Group and Count
// Count users by department
const results = await User.aggregate([
{ $group: { _id: '$department', count: { $sum: 1 } } }
])
console.log(results)
// [
// { _id: 'Engineering', count: 45 },
// { _id: 'Sales', count: 32 },
// { _id: 'Marketing', count: 18 }
// ]
Average by Category
// Calculate average price per product category
const avgPrices = await Product.aggregate([
{
$group: {
_id: '$category',
avgPrice: { $avg: '$price' },
count: { $sum: 1 }
}
},
{ $sort: { avgPrice: -1 } }
])
Complex Pipeline
// Sales analytics with multiple stages
const salesReport = await Order.aggregate([
// Filter completed orders from last month
{
$match: {
status: 'completed',
createdAt: { $gte: startOfMonth }
}
},
// Group by product and calculate metrics
{
$group: {
_id: '$productId',
totalRevenue: { $sum: '$amount' },
orderCount: { $sum: 1 },
avgOrderValue: { $avg: '$amount' }
}
},
// Sort by revenue
{ $sort: { totalRevenue: -1 } },
// Limit to top 10
{ $limit: 10 }
])
Join Collections (Lookup)
// Join users with their orders
const usersWithOrders = await User.aggregate([
{
$lookup: {
from: 'orders',
localField: '_id',
foreignField: 'userId',
as: 'orders'
}
},
{
$project: {
name: 1,
email: 1,
orderCount: { $size: '$orders' },
totalSpent: { $sum: '$orders.amount' }
}
}
])
Date-based Aggregation
// Daily revenue for the last 30 days
const dailyRevenue = await Order.aggregate([
{
$match: {
createdAt: { $gte: thirtyDaysAgo }
}
},
{
$group: {
_id: {
$dateToString: { format: '%Y-%m-%d', date: '$createdAt' }
},
revenue: { $sum: '$amount' },
orders: { $sum: 1 }
}
},
{ $sort: { _id: 1 } }
])
Combined Usage
// Comprehensive performance analysis
class PerformanceMonitor {
static async getMetrics(endpoint: string) {
const metrics = await ApiMetric.where('endpoint', endpoint)
return {
count: await metrics.count(),
min: await metrics.min('responseTime'),
max: await metrics.max('responseTime'),
avg: await metrics.average('responseTime'),
p50: await metrics.percentile('responseTime', 50),
p95: await metrics.percentile('responseTime', 95),
p99: await metrics.percentile('responseTime', 99)
}
}
static async getTopSlowestEndpoints() {
return await ApiMetric.aggregate([
{
$group: {
_id: '$endpoint',
avgTime: { $avg: '$responseTime' },
p95: { $percentile: { input: '$responseTime', p: [0.95] } }
}
},
{ $sort: { avgTime: -1 } },
{ $limit: 10 }
])
}
}
Use Cases
percentile()
- SLA Monitoring: Track p95/p99 response times
- Performance Analysis: Understand distribution of metrics
- Capacity Planning: Identify outliers and trends
- Quality Metrics: Analyze test scores and ratings
aggregate()
- Business Intelligence: Complex reporting and analytics
- Data Transformation: Reshape data for different views
- Multi-collection Analysis: Join and analyze related data
- Time-series Analysis: Aggregate metrics over time periods
Additional Resources