1

我有多个网站,每个网站都有访问者“触发”我想要跟踪的多个事件。我有来自所有网站的这些事件的日志,每个事件都填充了网站 ID、事件名称和执行该事件的用户 ID(为了简单起见,假设就是这样)。

要求:

  1. 能够根据网站 ID 和事件名称获取有多少唯一访问者获得了它。
  2. 这也应该支持日期范围(范围内不同的唯一访问者)。

我正在考虑使用以下数据模型(例如)为每个“网站 ID”创建一个集合:

collection ev_{websiteId}:
[
    {
        _id: "error"
        dailyStats: [
            {
                _id: 20121005 <-- (yyyyMMdd int, should be indexed!)
                hits: 5
                users: [ 
                         {
                            _id: 1, <-- should be indexed!
                            hits: 1
                         }, 
                         {
                            _id: 2
                            hits: 3
                         },
                         {
                            _id: 3,
                            hits: 1
                         }
                ]
            },
            {
                _id: 20121004 
                hits: 8
                users: [ 
                         {
                            _id: 1,
                            hits: 2
                         }, 
                         {
                            _id: 2
                            hits: 3
                         },
                         {
                            _id: 3,
                            hits: 3
                         }
                ]
            },
        ]
    },
    {
        _id: "pageViews"
        dailyStats: [
            {
                _id: 20121005 
                hits: 500
                users: [ 
                         {
                            _id: 1, 
                            hits: 100
                         }, 
                         {
                            _id: 2
                            hits: 300
                         },
                         {
                            _id: 3,
                            hits: 100
                         }
                ]
            },
            {
                _id: 20121004
                hits: 800
                users: [ 
                         {
                            _id: 1, 
                            hits: 200
                         }, 
                         {
                            _id: 2
                            hits: 300
                         },
                         {
                            _id: 3,
                            hits: 300
                         }
                ]
            },
        ]
    },
]

我正在使用 _id 来保存事件 ID。我正在使用 dailyStats._id 来保存它发生的时间(yyyyMMdd 格式的整数)。我使用 dailySattes.users._id 来表示用户的唯一 ID 哈希。

为了获得唯一用户,我基本上应该能够在给定的日期范围内运行(mapreduce?)数组中不同的计数项目(我会将日期范围转换为 yyyyMMdd)。

我的问题:

  1. 这个数据模型对你有意义吗?我担心随着时间的推移这个模型的可扩展性(如果我在某些客户端中有很多每日唯一访问者,它会导致一个巨大的文档)。我正在考虑按 _id < [date as yyyyMMdd] 删除 dailyStats 文档。通过这种方式,我可以将文档大小保持在合理的范围内,但这里仍然存在限制。
  2. 是否有一种简单的方法来运行“upsert”,如果尚未创建也将创建 dailyStats,添加用户(如果尚未创建)并增加两者的“hits”属性?
  3. map-reduce 怎么样?您将如何处理它(需要在给定日期范围内的所有子文档的 users._id 上运行不同)?新的聚合框架有没有更简单的方法?

顺便说一句 - 解决唯一访问者的另一种选择是使用 Redis 位图,但我不确定是否值得持有多个数据存储(维护方面)。

4

1 回答 1

1

对当前上述架构的评论很少。

正如您所指出的可扩展性以及您真正在做多少预聚合,我有点担心。

我在做指标时使用过的大多数 Mongo 实例都与您指出的情况相似,但您似乎确实严重依赖于对单个文档进行更新并插入其中的各个部分,这将减慢速度并可能导致有点锁定..

我可能会建议一条不同的路径,Mongo 甚至在与他们谈论做指标时建议的路径。看到你已经有了一个你想要做的结构,我会按照以下方式创建一些东西:

{
  "_id":"20121005_siteKey_page",
  "hits":512,
  "users":[
   {
     "uid":5, 
     "hits":512,
   }
}

通过这种方式,您可以将文档大小限制为可以合理进行快速 upserts 的内容。从这里您可以批量执行 mapreduce 作业,以进一步扩展您想要查看的内容。

这还取决于您的最终目标,您是否希望提供实时指标?你试图获得什么样的粒度?Redis Maps 可能是您至少想看看的东西:Great article here

不管这是一个有趣的问题要解决:)

希望这有帮助!

于 2012-10-24T13:14:11.487 回答