php - mongo发现用户订阅了至少n天

标签 php mongodb mongodb-query

考虑我有如下 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/

相关文章:

php - Laravel 使用 XML 测试 POST 路由

java - 使用 Mongo Cursor 时更新文档的正确方法是什么?

sql - Simba Mongodb ODBC 驱动程序 : returned data that does not match expected data length

mongodb - 在元素不存在的地方插入数组,否则更新它(有多个条件)

javascript - 遍历数组并执行 MongoDB 查询(NodeJS)

mongodb - 计算 MongoDB 中另一个字段分组的文档中某个字段中字符串实例的数量?

php : simple azure login with info

php - 如何连接具有不同关系的多个表并在 Laravel 5.3 中使用 attach()

node.js - 在生产环境中运行 mongodb

php - 基于用户的子域