我有多个网站,每个网站都有访问者“触发”我想要跟踪的多个事件。我有来自所有网站的这些事件的日志,每个事件都填充了网站 ID、事件名称和执行该事件的用户 ID(为了简单起见,假设就是这样)。
要求:
- 能够根据网站 ID 和事件名称获取有多少唯一访问者获得了它。
- 这也应该支持日期范围(范围内不同的唯一访问者)。
我正在考虑使用以下数据模型(例如)为每个“网站 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)。
我的问题:
- 这个数据模型对你有意义吗?我担心随着时间的推移这个模型的可扩展性(如果我在某些客户端中有很多每日唯一访问者,它会导致一个巨大的文档)。我正在考虑按 _id < [date as yyyyMMdd] 删除 dailyStats 文档。通过这种方式,我可以将文档大小保持在合理的范围内,但这里仍然存在限制。
- 是否有一种简单的方法来运行“upsert”,如果尚未创建也将创建 dailyStats,添加用户(如果尚未创建)并增加两者的“hits”属性?
- map-reduce 怎么样?您将如何处理它(需要在给定日期范围内的所有子文档的 users._id 上运行不同)?新的聚合框架有没有更简单的方法?
顺便说一句 - 解决唯一访问者的另一种选择是使用 Redis 位图,但我不确定是否值得持有多个数据存储(维护方面)。