如何使用Map / Reduce和MongoDB按链接的文档属性进行分组

时间:2012-06-07 15:49:05

标签: javascript mongodb mapreduce

我正在尝试找出一种使用MongoDB和Map / Reduce按人口统计分组用户网站访问的好方法。我有以下收藏品:

网站访问 - 示例:

{
    userId: '184792',
    resource: '/example/foo',
    visitTime: ISODate(...)
}

用户个人资料 - 示例:

{
    userId: '184792',
    demo: '18-30',
    city: 'Austin',
    state: 'TX',
    ...
}

我想生成一份报告,按人口统计显示每日或每月的网站访问次数。但是,如果我在网站访问时执行Map / Reduce,我只能访问userId,而不能访问人口统计信息,因此我无法根据人口统计信息发出密钥。事实上,如果我想按任何用户属性(如State)进行分组,那也是不可能的。

有谁知道在MongoDB中解决这个问题的最佳实践方法是什么?我应该复制每个站点访问文档中的所有用户属性吗?我应该在应用程序代码中进行某种类型的重新缩减,我可以使用多个查询加入集合吗?或者我只是使用错误的工具来解决这类问题?

感谢您的任何建议。

2 个答案:

答案 0 :(得分:0)

这里有三种解决方案:

  1. 将人口统计数据归一化为网站访问。
  2. 做一个“客户端”Map / Reduce。即:编写一个循环访问的脚本,加载相应的用户配置文件,然后更新摘要集合。
  3. 为此保留实时计数器。
  4.   

    有谁知道解决这个问题的最佳实践方法是MongoDB?

    使用MongoDB,答案通常是“它取决于”。在这种情况下,确实如此。

    需要考虑的一些问题:

    • 您是否已在每次访问时查找个人资料数据?
    • 您想要数据“实时”吗?
    • 您是否事先知道所有预期的汇总?
    • 您想存储所有交易数据还是只关心汇总?

    通常,此处的解决方案是#1& #3。

    如果您想要交易数据和“灵活”报告,那么您需要在每次访问时保留个人资料数据。

    如果您事先了解主要报告,那么我建议您使用某种形式的计数器,并在编写交易的同时写入这些报告。因此,您基本上可以动态构建报表数据集。是的,这是更多的写作,但MongoDB赞成这种做大量写入的模式。

答案 1 :(得分:0)

您可以使用reduce输出选项实际上将两个地图缩小结果合并在一起。

  

{reduce:" collectionName" } - 如果存在给定密钥的文档   结果集和旧集合中的reduce操作   (将使用指定的reduce函数)将对两者执行   值和结果将写入输出集合。如果一个   提供了finalize函数,这将在reduce之后运行   好。

您需要将两个集合映射到一个通用格式,以便您可以执行此缩减步骤,对每个源映射文档中的一个文档执行操作,并合并每个集合中的相应字段。

有关示例,请参阅this blog entry