我有一个包含以下数据的集合:
{
"_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
}
]
}
我想进行聚合,以便我知道某位乘客的次数,与某位驾驶员相关的时间,在我的例子中,它将是:
for user1:[{ driver: user2, times: 2}]
for user2:[{ driver: user1, times: 2}]
for user3:[{ driver: user1, times: 3}, {driver: user2, times:2}]
我是mongo的新手,并且知道如何使用sum执行简单的聚合,但不是当它的内部数组,以及当我的主题本身在数组中时。 什么是执行这种聚合的适当方式,更具体地说,我是如何在基于express.js的服务器中执行它的?
答案 0 :(得分:14)
为了通过聚合框架实现您的需求,第一个管道阶段将对相关乘客进行$match
操作,该操作将文档与乘客阵列中的用户进行匹配,然后进行$unwind
操作它从先前操作中的输入文档解构乘客阵列,以输出每个元素的文档。在解构数组上的另一个 $match
操作跟随进一步过滤前一个文档流,只允许匹配的文档未经修改地传递到下一个管道阶段,该阶段使用{{投影所需的字段3}}运算符。基本上,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
管道阶段之前执行$project
操作,您可以计算总乘客时间使用 $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
}