【问题标题】:Aggregate Field Values to Separate Key Names聚合字段值以分隔键名
【发布时间】:2015-10-28 07:10:39
【问题描述】:

我在 MongoDB 中有一个集合,其中包含类似这样的示例数据(简化):

{
    _id: 1,
    username: "ted",
    content: "4125151",
    status: "complete"
}
{
    _id: 2,
    username: "sam",
    content: "4151",
    status: "new"
}
{
    _id: 3,
    username: "ted",
    content: "511",
    status: "new"
}
{
    _id: 4,
    username: "ted",
    content: "411",
    status: "in_progress"
}
{
    _id: 5,
    username: "pat",
    content: "1sds51",
    status: "complete"
}
{
    _id: 6,
    username: "ted",
    content: "4151",
    status: "in_progress"
}
{
    _id: 7,
    username: "ted",
    content: "4125",
    status: "in_progress"
}

我需要汇总数据,以便为每个用户获取每个状态值的计数以及记录总数。结果应如下所示:

[
{
    username: “pat”,
    new: 0,
    in_progress: 0,
    complete: 1,
    total: 1
},

{
    username: “sam”,
    new: 1,
    in_progress: 0,
    complete: 0,
    total: 1
},

{
    username: “ted”,
    new: 1,
    in_progress: 3,
    complete: 1,
    total: 5
}
]

或者任何可以有效服务于相同目的的格式,我希望能够与 ngRepeat 一起使用以这种格式显示在前端:

User    New     In Progress Complete    Total
pat     0       0           1           1
sam     1       0           0           1
ted     1       3           1           5

我可以执行这个聚合:

{
    "$group": {
        "_id": {
            "username": "$username",
            "status": "$status"
        },
        "count": {
            "$sum": 1
        }
    }
}

这为我提供了至少有一条记录的每个用户/状态组合的单独计数。但是我必须把它拼凑起来,以得到我可以在前端使用的格式。这一点都不理想。

有没有办法执行聚合以获取我需要的格式的数据?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您需要的是值的“条件”聚合,以便为每个状态生成不同的字段属性。

    使用$cond 运算符非常简单:

    [
        { "$group": {
            "_id": "$username",
            "new": { "$sum": { "$cond": [{ "$eq": [ "$status", "new" ] },1,0 ] } },
            "complete": { "$sum": { "$cond": [{ "$eq": [ "$status", "complete" ] },1,0 ] } },
            "in_progress": { "$sum": { "$cond": [{ "$eq": [ "$status", "in_progress" ] },1,0 ] } },
            "total": { "$sum": 1 }
        }}
    ]
    

    当然假设这些是唯一的“状态”值,但如果它们不是,那么只需添加一个额外的 $project 来汇总您想要的字段:

    [
        { "$match": { "status": { "$in": [ "new", "complete", "in_progress" ] } } },
        { "$group": {
            "_id": "$username",
            "new": { "$sum": { "$cond": [{ "$eq": [ "$status", "new" ] },1,0 ] } },
            "complete": { "$sum": { "$cond": [{ "$eq": [ "$status", "complete" ] },1,0 ] } },
            "in_progress": { "$sum": { "$cond": [{ "$eq": [ "$status", "in_progress" ] },1,0 ] } }
        }},
        { "$project": {
            "new": 1,
            "complete": 1,
            "in_progress": 1,
            "total": { "$add": [ "$new", "$complete", "$in_progress" ] }
    ]
    

    或者只是将 $add 包含在 $group 中,对单独的字段进行相同的计算。但是,如果确实存在您不想要的其他状态值,$match 可能只是最好的主意。

    【讨论】:

      【解决方案2】:

      另一个使用 $group 两次和 $push 的答案,在下面的查询中,您需要计算 UI 端的最终总数。

          db.collection.aggregate([
        {
          "$group": {
            "_id": {
              "username": "$username",
              "status": "$status"
            },
            "statuscount": {
              "$sum": 1
            }
          }
        },
        {
          "$group": {
            "_id": "$_id.username",
            "finalstatus": {
              "$push": {
                "Status": "$_id.status",
                "statuscount": "$statuscount"
              }
            }
          }
        }
      ])
      

      【讨论】:

        猜你喜欢
        • 2015-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-26
        • 1970-01-01
        • 2015-08-02
        • 1970-01-01
        • 2016-05-12
        相关资源
        最近更新 更多