Reputation: 986
I have two collections — customers
and trips
:
An example document in customers where _id
is a unique ID assigned to each customer:
{
"_id": ObjectId("59caa2660d09740010eccfde")
}
An example document in trips where userId
is the _id
of the customer who took the trip, duration
is the trip duration in minutes and endtime
is the time at which that particular trip ended (_id
here doesn't really matter):
{
"_id" : ObjectId("59fe73be50fe7600169bcdb5"),
"userId": ObjectId("59caa2660d09740010eccfde"),
"duration": NumberInt(54),
"endtime": ISODate("2017-11-03T08:14:45.193+0000")
}
On using $lookup
to "left outer join" trips
to customers
, I have several hundred documents and each customer has trips (zero or more) associated with them:
{
"_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")
}
]
}
I want to fetch all active customers where an active customer is anyone who:
Upvotes: 1
Views: 672
Reputation: 103395
You would want to have the $lookup
pipeline stage as the last or one of the last after grouping the trips collection calculating the aggregates and then filter.
So, for the first condition you need to get all the last four weeks documents from the trips collection, group them by userId
and one week interval and aggregate the times:
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"
}
}
])
Upvotes: 1