根据 mongodb 个事件计算 DAU/MAU

Calculate DAU/MAU from mongodb events

目前情况如下:

  collection.aggregate(
    [
      {
        $match: {
          ct: {$gte: dateFrom, $lt: dateTo },
        }
      },
      {
        $group: { 
          _id: '$user'
        }
      }
    ]
  ).toArray((err, result) => {
    callback(err, result.length)
  });

这让我得到了一个这样的用户列表,我可以算作 DAU/MAU:

但我认为这样做效率不高,正确的做法是什么?

我对一个大型事件数据库进行了快速测试,如果您有正确的索引,使用不同的计数比聚合要快得多:

collection.distinct('user', { ct: { $gte: dateFrom, $lt: dateTo } }).length

您可以针对每天和每月的唯一活跃用户使用以下聚合。我假设 ct 作为时间戳字段。

db.collection.aggregate(
[
  {"$match":{"ct":{"$gte":dateFrom,"$lt":dateTo}}},
  {"$facet":{
    "dau":[
      {"$group":{
        "_id":{
          "user":"$user",
          "ymd":{"$dateToString":{"format":"%Y-%m-%d","date":"$ct"}}
        }
      }},
      {"$group":{"_id":"$_id.ymd","dau":{"$sum":1}}}
    ],
    "mau":[
      {"$group":{
        "_id":{
          "user":"$user",
          "ym":{"$dateToString":{"format":"%Y-%m","date":"$ct"}}
        }
      }},
      {"$group":{"_id":"$_id.ym","mau":{"$sum":1}}}
    ]
  }}
])

DAU

db.collection.aggregate(
[
  {"$match":{"ct":{"$gte":dateFrom,"$lt":dateTo}}},
  {"$group":{
     "_id":{
        "user":"$user",
        "ymd":{"$dateToString":{"format":"%Y-%m-%d","date":"$ct"}}
      }
   }},
   {"$group":{"_id":"$_id.ymd","dau":{"$sum":1}}}
])

月活跃用户

db.collection.aggregate(
[
  {"$match":{"ct":{"$gte":dateFrom,"$lt":dateTo}}},
  {"$group":{
     "_id":{
       "user":"$user",
       "ym":{"$dateToString":{"format":"%Y-%m","date":"$ct"}}
     }
  }},
  {"$group":{"_id":"$_id.ym","mau":{"$sum":1}}}
])

可以在分组时使用sum

collection.aggregate([
    { $match: {'date': {$gte: dateFrom, $lt: dateTo }}}, // fetch all requests from/to 
    { $group: { _id: '$user', total: { $sum: 1 }}}, // group all requests by user and sum the count of collection for a group
    { $sort: { total: -1 }}
  ], function (err, result) {
      if (err) cb(err, null);
      cb(null, result);
  });