Монго найти пользователей были подписаны по крайней мере, n дней - PullRequest
0 голосов
/ 12 ноября 2018

считают, что у меня есть коллекция 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 дней.каждый пользователь может подписываться и отписываться неограниченное количество раз.Например, пользователь А может подписаться 100 раз и отписаться 100 раз.

, как вы видите, в моих документах есть поле с именем action.Другими словами, мне нужно найти записи для пользователя с интервалом не менее 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 дней.рассмотрим пользователя А, подписавшегося на мой сервис, и через 3 дня отписаться.

и в следующий раз пользователь А снова подписаться на мой сервис и отписаться через 5 дней.Максимальное количество дней подписки для этого пользователя составляет 5

1014 * мой стек: mongodb: 4.0.0

php: 7.2

Ответы [ 3 ]

0 голосов
/ 13 ноября 2018

Я полагаю, что более точно, если вы обрабатываете каждый период после каждого unsubscribe действия для определенного пользователя. В качестве иллюстрации, если пользователь A делает unsubscribe каждый раз, вы рассчитаете последний период подписки и обновите его на соединении подписка-пользователь. Я утверждаю, что вы можете управлять, если у вас более одной подписки на пользователя, и вы всегда можете отслеживать точное время каждой подписки для каждого клиента.

Однако вы можете отследить это время с помощью задания, которое выполняется с точным интервалом времени.

0 голосов
/ 13 ноября 2018

Я думаю, что это может быть агрегат, который вы ищете:

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
    }
]

Я протестировал с некоторыми образцами документов, и он работал хорошо,Надеюсь, это работает для вас.

0 голосов
/ 12 ноября 2018

Функция агрегирования будет возвращать список событий подписки и отмены подписки с датой user_id

db.getCollection('').aggregate([
     {
       $group:
         {
           _id: "$user_id",

           "subscribe_unsubscribe" :
                        {
                          $push:
                            {
                                $cond: { if: { $eq: [ "$action", "subscribe" ] }, then: {"s":"$created_at"}, else: {"u":"$created_at"} }

                            }
                         }
         }
     }]
   )

Вывод будет выглядеть как

[{
    "_id" : "3334",
    "subscribe_unsubscribe" : [ 
        {
            "s" : 2000-11-12 00:00:00.000Z
        }, 
        {
            "u" : 2000-11-13 00:00:00.000Z
        },
        {
            "s" : 2000-11-16 00:00:00.000Z
        }, 
        {
            "u" : 2000-11-20 00:00:00.000Z
        }
    ]
},
...
]

Теперь вы можете использоватьсерверный скрипт, чтобы получить максимальное количество дней.или вы можете написать другую конвейерную операцию, которая получит максимальную разницу шаблонных последовательных элементов.

Проверка агрегата mongodDB

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...