set
Sets the criteria to group by.
If this function is not called, the group stage results in a single document that folds over the entire pipeline results.
If this function is called, documents are grouped by equality of the value, each group results in a document that folds over the documents in the group.
This function can only be called on the _id field or one of its subfields.
Simple example
We can compute the average age of users in the different cities we have users in:
class User(
val _id: ObjectId,
val name: String,
val age: Int,
val city: String,
)
class AgePerCity(
val _id: String,
val averageAge: Double,
)
users.aggregate()
.group {
// Group by city name
AgePerCity::_id set User::city
// Calculate average age within each city
AgePerCity::averageAge average User::age
}Each city in the dataset returns a document with _id set to the city name, and averageAge set to the average age of users in that city.
Compound example
We can also compute more complex groups, where the _id is composed of multiple fields. To do so, they must all be nested within the _id field itself.
For example, if we want to create different groups for different age ranges:
class User(
val _id: ObjectId,
val name: String,
val age: Int,
val city: String,
)
enum class AgeRange {
Child,
Adult,
Elder,
}
class AgePerCityAndRangeId(
val city: String,
val ageRange: AgeRange,
)
class AgePerCityAndRange(
val _id: AgePerCityAndRangeId,
val averageAge: Double,
val medianAge: Int,
)
users.aggregate()
.group {
// Group by city name
AgePerCityAndRange::_id / AgePerCityAndRangeId::city set User::city
// Also group by age range
AgePerCityAndRange::_id / AgePerCityAndRangeId::ageRange set switch(
User::age lt 18 then AgeRange.Child,
User::age gte 65 then AgeRange.Elder,
default = AgeRange.Adult,
)
// In each group, compute the average age
AgePerCityAndRange::averageAge average User::age
// In each group, count the number of users
AgePerCityAndRange::medianAge median User::age
}