сохранение полей, свернутых $group

#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 этап после группы.