Aggregations
The ODM provides a type-safe API for performing server-side aggregations, allowing you to efficiently calculate values like count
, sum
, and average
across a set of documents without needing to download all the data to the client.
count()
The simplest aggregation is .count()
, which returns the number of documents matching your query.
// Get the total number of users
final userCount = await db.users.count().get();
// Get the number of active users
final activeUserCount = await db.users
.where(($) => $.isActive(isEqualTo: true))
.count()
.get();
print('There are $activeUserCount active users.');
aggregate()
For more complex aggregations, use the .aggregate()
method. It allows you to perform multiple calculations (sum
, average
, and count
) in a single request. The result is returned as a strongly-typed Record.
// Get multiple stats for active users in one go
final stats = await db.users
.where(($) => $.isActive(isEqualTo: true))
.aggregate(($) => (
// You can name the fields whatever you want
totalUsers: $.count(),
averageAge: $.age.average(),
totalFollowers: $.profile.followers.sum(),
))
.get();
print('Total active users: ${stats.totalUsers}');
print('Average age of active users: ${stats.averageAge}');
print('Combined followers of all active users: ${stats.totalFollowers}');
Streaming Aggregations (A Unique Feature)
A powerful and unique feature of this ODM is the ability to create real-time subscriptions to aggregation results. While Firestore does not support this natively, our ODM implements this on the client-side for you.
When you call .stream
on an aggregate()
or count()
query, the ODM:
- Creates a real-time subscription to the underlying query.
- Whenever the query results change, it efficiently recalculates the aggregations on the client.
- It then emits the new aggregation results on the stream.
This allows you to build reactive UIs that display live-updating stats.
// Create a stream that emits the latest stats whenever the data changes
final statsStream = db.users
.where(($) => $.isActive(isEqualTo: true))
.aggregate(($) => (
count: $.count(),
avgAge: $.age.average(),
))
.stream;
// Listen to the stream and update your UI
statsStream.listen((stats) {
print('Live active user count: ${stats.count}');
print('Live average age: ${stats.avgAge}');
});