#mongodb #mongodb-query #aggregation-framework
#mongodb #mongodb-запрос #агрегация-фреймворк
Вопрос:
Я хочу суммировать набор документов , рассчитывая на поле с именем code
. Как я могу обобщить свои данные и сохранить детали из исходных документов?
Входные данные конвейера содержат приведенные ниже документы.
{
"_id" : ObjectId("5ff38e0eb09dec2cbce14760"),
"code" : "U",
"date" : ISODate("2021-04-09T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
"student_id" : 9441
}
{
"_id" : ObjectId("5ff38e0eb09dec2cbce14807"),
"code" : "E",
"date" : ISODate("2020-11-02T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
"student_id" : 9441
}
{
"_id" : ObjectId("5ff39854b09dec2cbce1494c"),
"code" : "E",
"date" : ISODate("2020-11-03T08:00:00.000 0000"),
"full_day" : true,
"remote" : false,
"student_id" : 9441
}
Желаемый результат группируется по code
, продвигается student_id
до корневого уровня и помещает другие сведения в details
массив:
{
"code" : "U",
"student_id": 9441,
"count" : 1.0,
"details" : [
{
"date" : ISODate("2021-04-09T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
}
]
}
{
"code" : "E",
"student_id": 9441,
"count" : 2.0,
"details" : [
{
"date" : ISODate("2020-11-02T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
},
{
"date" : ISODate("2020-11-03T08:00:00.000 0000"),
"full_day" : true,
"remote" : false,
}
]
}
Объединение $group
, и $push
я смог только произвести:
{
"_id" : "U",
"count" : 1.0,
"details" : [
{
"date" : ISODate("2021-04-09T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
"student_id" : 9441
}
]
}
{
"_id" : "E",
"count" : 2.0,
"details" : [
{
"date" : ISODate("2020-11-02T00:00:00.000 0000"),
"full_day" : false,
"remote" : false,
"student_id" : 9441
},
{
"date" : ISODate("2020-11-03T08:00:00.000 0000"),
"full_day" : true,
"remote" : false,
"student_id" : 9441.0
}
]
}
Вышеуказанные результаты были достигнуты с помощью этого конвейера:
[
{
"$match" : {
"student_id" : 9441.0
}
},
{
"$group" : {
"_id" : "$code",
"count" : {
"$sum" : 1.0
},
"details" : {
"$push" : {
"date" : "$date",
"full_day" : "$full_day",
"remote" : "$remote",
"student_id" : "$student_id"
}
}
}
},
{
"$addFields" : {
"student_id" : "$student_id"
}
}
]
Комментарии:
1. Можем ли мы увидеть конвейер агрегации, который вы использовали?
2. Конвейер добавлен в исходное сообщение. Спасибо!
3. Возможно ли иметь другой student_id с одним и тем же кодом? Если да, следует ли их учитывать вместе или по отдельности?
4. Первым шагом в конвейере является
$match
включениеstudent_id
. Таким образом, я не ожидаю, что когда-либо в эту часть конвейера будут входить разные идентификаторы учащихся.
Ответ №1:
Если вы ожидаете, что все входные документы будут иметь одинаковое значение для поля, и хотите, чтобы это поле было включено в $group
выходные данные, используйте оператор накопления $first:
{
"$group" : {
"_id" : "$code",
"student_id" : {$first: "$student_id"},
"count" : {
"$sum" : 1.0
},
"details" : {
"$push" : {
"date" : "$date",
"full_day" : "$full_day",
"remote" : "$remote"
}
}
}
}
Если вам нужно переименовать _id
обратно в code
, используйте $project
этап после группы.