【问题标题】:MongoDB Aggregation with sum of array valuesMongoDB聚合与数组值的总和
【发布时间】:2015-03-28 16:46:11
【问题描述】:

我有一个包含以下数据的集合:

{
    "_id" : ObjectId("5516d416d0c2323619ddbca8"),
    "date" : "28/02/2015",
    "driver" : "user1",
    "passengers" : [
        {
            "user" : "user2",
            "times" : 2
        },
        {
            "user" : "user3",
            "times" : 3
        }
    ]
}
{
    "_id" : ObjectId("5516d517d0c2323619ddbca9"),
    "date" : "27/02/2015",
    "driver" : "user2",
    "passengers" : [
        {
            "user" : "user1",
            "times" : 2
        },
        {
            "user" : "user3",
            "times" : 2
        }
    ]
}

并且我想执行聚合,以便我知道某个乘客的时间,它与某个驾驶员在一起,在我的示例中它将是: 对于用户 1:[{ driver: user2, times: 2}] 对于用户 2:[{ driver: user1, times: 2}] 对于用户 3:[{ driver: user1, times: 3}, {driver: user2, times:2}]

我对 mongo 很陌生,知道如何使用 sum 执行简单的聚合,但不是当它在数组内部时,当我的主题本身在数组中时。 执行这种聚合的适当方法是什么,更具体地说,我如何在基于 express.js 的服务器中执行它?

【问题讨论】:

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

为了通过聚合框架满足您的需求,第一个管道阶段将是对相关乘客执行 $match 操作,将文档与乘客数组中的用户进行匹配,然后是 $unwind 操作,用于解构乘客数组从先前操作中的输入文档中为每个元素输出一个文档。解构后的数组上的另一个 $match 操作进一步过滤了先前的文档流,以仅允许匹配的文档未经修改地传递到下一个管道阶段,该阶段使用 $project 运算符投影所需字段.所以基本上你的user3 的聚合管道就像:

db.collection.aggregate([
     {
        "$match": {
            "passengers.user": "user3"
        }
     },
     {
         "$unwind": "$passengers"
     },
     {
        "$match": {
            "passengers.user": "user3"
        }
     },
     {
         "$project": {
             "_id": 0,
            "driver": "$driver",
            "times": "$passengers.times"
        }
     }
])

结果

/* 0 */
{
    "result" : [ 
        {
            "driver" : "user1",
            "times" : 3
        }, 
        {
            "driver" : "user2",
            "times" : 2
        }
    ],
    "ok" : 1
}

更新

为了对不同日期的司机进行分组,正如您所提到的,您可以在最后一个 $project 管道阶段之前执行 $group 操作,您可以使用 计算总乘客时间>$sum 运营商:

db.collection.aggregate([
     {
        "$match": {
            "passengers.user": "user3"
        }
     },
     {
         "$unwind": "$passengers"
     },
     {
        "$match": {
            "passengers.user": "user3"
        }
     },
     {
         "$group": {
             "_id": "$driver", 
             "total": {
                 "$sum": "$passengers.times"
             }
         }
     },
     {
         "$project": {
            "_id": 0,
            "driver": "$_id",
            "total": 1
        }
     }
])

结果

/* 0 */
{
    "result" : [ 
        {
            "total" : 2,
            "driver" : "user2"
        }, 
        {
            "total" : 3,
            "driver" : "user1"
        }
    ],
    "ok" : 1
}

【讨论】:

  • 谢谢,这非常符合我的需求(它没有将不同日期的重复驱动程序分组)。我最终使用了$group: {"_id": "$driver", "total": {$sum: "$passengers.times"}}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 2018-06-03
  • 2022-10-13
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
相关资源
最近更新 更多