Aggregates and Reporting
Use aggregate helpers, groupBy, having, and report-style selects
Aggregate helpers
Aggregate terminals follow the same shape as count(): single column in, scalar out.
await db.orders.where({ status: 'paid' }).sum('amount'); // -> number | null
await db.orders.avg('amount'); // -> number | null
await db.users.min('createdAt'); // -> number | null
await db.users.max('createdAt'); // -> number | null
JSON path columns work too:
await db.orders.sum('payload.amount');
groupBy + having + object-form select
For reporting queries, select accepts an object form that projects plain columns alongside aggregates. Each entry key becomes the SQL alias.
db.posts
.where({ published: 1 })
.select({
userId: true,
total: { sum: 'views' },
n: { count: '*' },
})
.groupBy('userId') // single col or array
.having({ total: { gte: 1000 }, n: { gte: 5 } })
.orderBy({ total: 'desc' })
.limit(10)
.many();
Aggregate types: count, countDistinct, sum, avg, min, max.
having reuses the full where vocabulary (gt, gte, lt, lte, eq, ne, between, notBetween, and so on) operating on the aliases from your select object.