考虑我有如下 user_events 集合:
[
{
"_id" : ObjectId("5be99dd1da8d4a596423a2d2"),
"user_id" : 203302,
"action" : "subscribe",
"created_at" : ISODate("2018-11-12T15:35:45.000Z"),
},
{
"_id" : ObjectId("5be99dd1da8d4a596423a2d2"),
"user_id" : 203302,
"action" : "unsubscribe",
"created_at" : ISODate("2018-10-12T15:35:45.000Z"),
},
...
]
我需要找到订阅我们服务至少n天的用户。 每个用户可以无限次订阅和取消订阅。 例如用户A可能订阅100次,退订100次。
如您所见,我的文档有一个名为“操作”的字段。 换句话说,我需要查找日期间隔至少为 n 天的用户的记录。
所以我的结果会是这样的:
[
{
"user_id": 2,
"max_subscription_days": 2
},
{
"user_id(user A)": 5,
"max_subscription_days": 3
},
{
"user_id": 11,
"max_subscription_days": 3
}
]
但我需要至少参与服务 n 天的用户。 假设用户 A 订阅了我的服务,并在 3 天后取消订阅。
下次用户A再次订阅我的服务并在5天后取消订阅。 因此该用户的最大订阅天数为 5 。
我的堆栈: mongodb:4.0.0
PHP:7.2
最佳答案
我认为这可能是您正在寻找的聚合:
db.user_events.aggregate([
{
$group: {
_id: "$user_id",
"events": {
$push: {
$cond: {
if: { $eq: [ "$action", "subscribe" ] },
then: {"date":"$created_at", "event": "subscribe"},
else: {"date":"$created_at", "event": "unsubscribe"}
}
}
}
}
},
{
$project : {
events: { $reverseArray : "$events" }
}
},
{
$project : {
user_id: "$_id",
max_subscription_days: {
$reduce : {
input: "$events",
initialValue: {date: null, max: 0},
in : {
date: {
$cond: {
if: { $eq : ["$$this.event", "unsubscribe"] },
then : "$$this.date",
else : null
}
},
max: {
$cond: {
if: { $eq : ["$$this.event", "unsubscribe"] },
then : "$$value.max",
else : {
$cond : {
if : { $gt : [ { $divide: [ { $subtract: [ "$$value.date", "$$this.date" ] }, 24 * 60 * 60 * 1000] }, "$$value.max" ] },
then : { $divide: [ { $subtract: [ "$$value.date", "$$this.date" ] }, 24 * 60 * 60 * 1000] },
else : "$$value.max"
}
}
}
}
}
}
}
}
},
{
$match : { "max_subscription_days.max" : { $gt : n } }
}
])
结果会是这样的:
[
{
"_id" : 203302,
"user_id" : 203302,
"max_subscription_days" : 10.0
},
{
"_id" : 203301,
"user_id" : 203301,
"max_subscription_days" : 4.0
}
]
我用一些示例文档进行了测试,效果很好。希望它对您有用。
关于php - mongo发现用户订阅了至少n天,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53265536/