MongoDB-使用多次查找的$ gruop,辅助$ group,$ sum字段

时间:2019-04-17 08:00:45

标签: node.js mongodb typescript mongodb-query aggregation-framework

我正在尝试使用mongo聚合查询来查看一堆数据,并以对我有用的方式对其进行检索。主要是因为我希望所有排序逻辑都在数据库上发生,而不是在服务器上手动完成。

所以我有 项目,用户,计时器

项目集合:

{id: 1, name: "project A"}
{id: 2, name: "project X"}
{id: 3, name: "project C"}

用户集合:

{id: 1, name: "John"}
{id: 2, name: "Jane"}
{id: 3, name: "James"}

计时器集合:

{id: 1, projectId: 3, userId: 2, startTime: (date ISO), endTime: (date ISO)}
{id: 2, projectId: 1, userId: 3, startTime: (date ISO), endTime: (date ISO)}
{id: 3, projectId: 1, userId: 1, startTime: (date ISO), endTime: (date ISO)}
{id: 4, projectId: 1, userId: 1, startTime: (date ISO), endTime: (date ISO)}
{id: 5, projectId: 2, userId: 1, startTime: (date ISO), endTime: (date ISO)}

我希望使用聚合从mongo中实现的是一个响应对象,该对象将反映“主要”类别的分组,其内部将按“次要”类别分组-每个条目将保存持续时间的总和(每个计时器的endTime减去startTime)

所以可以说我的主要小组是项目,而次要小组是用户,我还希望看到按字母顺序排列的名称,而不是ID。因此预期结果应该是:

[
    { project A: [
        { James: (*the sum of durations for all Jamses' timers on project 1*) },
        { John: (*the sum of durations for all John's timers on project 1*) },
                 ]
     },
    { project B: [
        { John: (*the sum of durations for all Jane's timers on project 3*) },
                 ]
     },
    { project X: [
        { Jane: (*the sum of durations for all John's timers on project 2*) },
                 ]
     },
]

如果有人可以尝试通过单个聚集调用实现此行为,我将很乐意。我已经尝试了管道运算符的许多组合,但是似乎无处可寻。

1 个答案:

答案 0 :(得分:0)

尝试如下:

db.timers.aggregate(
    [
        {
            $lookup: {
                from: "users",
                let: {"uId": "$userId" },
                pipeline: [
                    {
                        $match: {
                            $expr: { $eq: ["$_id", "$$uId"] }
                        }
                    }
                ],
                as: "userInfo"
            }  
        },
        {
            $lookup: {
                from: "project",
                let: {"pId": "$projectId" },
                pipeline: [
                    {
                        $match: {
                            $expr: { $eq: ["$_id", "$$pId"] }
                        }
                    }
                ],
                as: "projectInfo"
            }  
        },
        { $unwind: "$userInfo" },
        { $unwind: "$projectInfo" },
        {
            $group: {
                _id:  { "pname":"$projectInfo.name", "uname": "$userInfo.name" } ,
                sumOfDurationInMinutes: { $sum: { $divide:[ { $subtract: ["$endTime", "$startTime"] }, 60000 ]} } 
            }
        },
        {
            $group: {
                _id: "$_id.pname",
                data: { $push: "$$ROOT"}
            }
        }
    ]
)

响应结果:

{
    "_id" : "project C",
    "data" : [
        {
            "_id" : {
                "pname" : "project C",
                "uname" : "Jane"
            },
            "sumOfDurationInMinutes" : 60
        }
    ]
},

/* 2 */
{
    "_id" : "project A",
    "data" : [
        {
            "_id" : {
                "pname" : "project A",
                "uname" : "John"
            },
            "sumOfDurationInMinutes" : 120
        },
        {
            "_id" : {
                "pname" : "project A",
                "uname" : "James"
            },
            "sumOfDurationInMinutes" : 60
        }
    ]
},

/* 3 */
{
    "_id" : "project X",
    "data" : [
        {
            "_id" : {
                "pname" : "project X",
                "uname" : "John"
            },
            "sumOfDurationInMinutes" : 60
        }
    ]
}