Агрегация и конвейер
- Фреймворк агрегации позволяет обработать большое число документов в несколько стадий (запросов).
- Последовательность из нескольких стадий называется конвейером.
Запуск
mCourses.aggregate<Course>(
match(Course::name eq "Math"),
)
{"result": [{
"name": "Math",
"grades": [
{ "studentId": {"$oid": "643389b943f49536198c83e4"},
"date": 1681099194567,
"studentName": "Penny",
"value": 5 },
{ "studentId": {"$oid": "643389b943f49536198c83e5"},
"date": 1681099194567,
"studentName": "Amy",
"value": 5 },
...
]
}]}
Разворачивание
@Serializable
class UnwindCourse(
val name: String,
val grades: Grade
)
@Serializable
data class Course(
val name: String,
val grades: List<Grade> = emptyList()
)
mCourses.aggregate<UnwindCourse>(
unwind("\$grades")
)
Разворачивание. Результат
{"result": [
{ "name": "Math",
"grades": { "studentId": {"$oid": "..."},
"date":1681099194567, "studentName":"Penny", "value":5 }},
{ "name": "Math",
"grades": { "studentId": {"$oid": "..."},
"date":1681099194567, "studentName":"Amy", "value":5 }},
...
{ "name": "Phys",
"grades": { "studentId": {"$oid": "..."},
"date":1681099194568, "studentName":"Penny", "value":4 }},
...
]}
Применение разворачивания
mCourses.aggregate<UnwindCourse>(
unwind("\$grades"),
match(UnwindCourse::grades / Grade::studentName eq "Penny")
)
{"result": [
{ "name": "Math",
"grades": {"studentId": {"$oid": "..."},
"date":1681099194567, "studentName":"Penny", "value":5 }},
{ "name": "Phys",
"grades": {"studentId": {"$oid": "..."},
"date": 1681099194568, "studentName":"Penny", "value":4 }},
{ "name": "History",
"grades": {"studentId": {"$oid": "..."},
"date": 1681099194568, "studentName":"Penny", "value":5 }}
]}
Проекция. Цель
@Serializable
data class StudentGrade(
val value: Int? = null,
@Serializable(with = DateAsLongSerializer::class)
val date: Date? = null,
)
@Serializable
data class UnwindStudentCourse(
val name: String,
val grades: StudentGrade
)
Проекция. Результат
mCourses.aggregate<UnwindStudentCourse>(
unwind("\$grades"),
match(UnwindCourse::grades / Grade::studentName eq "Penny"),
project(
UnwindCourse::name,
UnwindCourse::grades / Grade::value,
UnwindCourse::grades / Grade::date ) )
{"result": [
{ "name": "Math",
"grades": {
"date": 1681099194567,
"value": 5 }},
{ "name": "Phys",
"grades": {
"date": 1681099194568,
"value": 4 } },
{ "name": "History",
"grades": {
"date": 1681099194568,
"value": 5 } } ] }
Дополнительные функции
mCourses.aggregate<UnwindStudentCourse>(
unwind("\$grades"),
match(UnwindCourse::grades / Grade::studentName eq "Penny"),
project(...),
sort(UnwindStudentCourse::grades / StudentGrade::value eq 1),
limit(2) )
{"result": [
{ "name": "Phys",
"grades": {
"date": 1681099194568,
"value": 4 } },
{ "name": "Math",
"grades": {
"date": 1681099194567,
"value": 5 } } ]}
Функции агрегирования
@Serializable data class Result(
val _id: String, val grades: Int)
mCourses.aggregate<Result>(
unwind("\$grades"),
group( UnwindCourse::grades / Grade::studentName,
Result::grades sum UnwindCourse::grades / Grade::value ) )
{"result": [
{ "_id": "Sheldon",
"grades": 15 },
{ "_id": "Leonard",
"grades": 12 },
{ "_id": "Howard",
"grades": 11 },
...
]}