我有两个收藏集 - customers
和trips
:
客户中的示例文档,其中_id
是分配给每个客户的唯一ID:
{
"_id": ObjectId("59caa2660d09740010eccfde")
}
行程中的示例文档,其中userId
是旅行客户的_id
,duration
是行程持续时间,以分钟为单位endtime
1}}是特定旅行结束的时间(_id
这里并不重要):
{
"_id" : ObjectId("59fe73be50fe7600169bcdb5"),
"userId": ObjectId("59caa2660d09740010eccfde"),
"duration": NumberInt(54),
"endtime": ISODate("2017-11-03T08:14:45.193+0000")
}
使用$lookup
到“左外连接”trips
到customers
时,我有几百个文档,每个客户都有与之相关的行程(零个或多个):
{
"_id": ObjectId("59caa2660d09740010eccfde"),
"trips": [
{
"_id" : ObjectId("59fe73be50fe7600169bcdb5"),
"userId": ObjectId("59caa2660d09740010eccfde"),
"duration": NumberInt(54),
"endtime": ISODate("2017-11-03T08:14:45.193+0000")
},
{
"_id" : ObjectId("5a5acb708e303e00109820ac"),
"userId": ObjectId("59caa2660d09740010eccfde"),
"duration": NumberInt(32),
"endtime": ISODate("2018-01-14T03:15:59.207+0000")
}
]
}
我想获取所有活跃客户,其中活跃客户是以下任何人:
答案 0 :(得分:1)
您希望将 $lookup
管道阶段作为分组计算聚合的旅行集合后的最后一个或最后一个,然后进行过滤。
因此,对于第一个条件,您需要从旅行集合中获取所有过去四周的所有文档,将它们按userId
分组并间隔一周并汇总时间:
var fourWeeksAgo = new Date();
fourWeeksAgo.setDate(fourWeeksAgo.getDate() - 28);
// var fourWeeksAgo = moment().subtract(4, "weeks").toDate();
db.trips.aggregate([
{ "$match": { "endtime": { "$gte": fourWeeksAgo } } },
{
"$group": {
"_id": {
"user": "$userId",
"weekInterval": {
"$subtract": [
{
"$subtract": ["$endtime", new Date("1970-01-01")]
},
{
"$mod": [
{ "$subtract": ["$endtime", new Date("1970-01-01")] },
1000 * 60 * 60 * 24 * 7
]
}
]
}
},
"count": { "$sum": 1 },
"totalDuration": { "$sum": "$duration" }
}
},
{
"$group": {
"_id": "$_id.user",
"weekCounts": {
"$push": {
"week": "$weekInterval",
"count": "$count",
"duration": "$totalDuration"
}
}
}
},
{
"$match": {
"weekCounts.1": { "$exists": true },
"$or": [
{ "weekCounts.count": { "$gte": 7 } },
{ "weekCounts.duration": { "$gte": 300 } }
]
}
},
{
"$lookup": {
"from": "users",
"localField": "_id",
"foreignField": "_id",
"as": "user"
}
}
])