假设我有三个基本模型:User、Company和Visit。每次用户访问公司时,都会以(user_id, company_id, visit_date)
格式记录访问。
我希望能够计算出一家公司访问之间的平均时间。不是总的访问量,而是他们的顾客在返回商店之前平均等待多长时间。
例如,如果一个用户在周二、周三和周五访问,则会给出一天的"间隔"和两天的"间隙"=>(1,2)。如果另一个用户在周一和周五访问,则间隔4天=>(4)。如果第三个用户只访问过一次,则不应考虑他。该公司用户访问之间的平均时间为(1+2+4)/3=2.33天。
如果我有成千上万的用户、水龙头和公司,并且我想为每个公司计算一个数字,我应该怎么做?我以前只做过基本的MapReduce应用程序,我不知道我的Map和Reduce步骤是什么。有人能帮我找出一个伪代码中的MapReduce吗?或者还有其他我可以合理执行的分布式计算方法吗?为了记录在案,我想每晚对我的数据库执行此操作。
过于简单的方法是有两个作业步骤。
第一个作业步骤有一个映射器,用于以"company:user"one_answers"visit_date"的形式写入键值。在上面的例子中,映射器会写一些类似的东西:
"user1:companyA" -> "2012/07/16"
"user1:comapnyA" -> "2012/07/17"
"user1:comapnyA" -> "2012/07/19"
"user2:comapnyA" -> "2012/07/15"
"user2:comapnyA" -> "2012/07/19"
...
这意味着,对reducer的每次调用都会将单个用户的所有访问传递给单个公司。这意味着对reducer的一个调用将传入:
"user1:companyA" -> {2012/07/16, 2012/07/17, 2012/07/19}
另一个呼叫将传入:
"user2:companyA" -> {2012/07/15, 2012/07/19}
我假设这组日期(作为Iterable值传入)在排序、找出差距并以"公司"one_answers"差距"的形式为每个差距写一条记录作为键值对时很容易管理。例如,当通过时:
"user1:companyA" -> {2012/07/16, 2012/07/17, 2012/07/19}
第一个作业的reducer将写入上下文:
"companyA" -> 1
"compnayA" -> 2
第二个作业有一个传递映射器,它只将公司/间隙信息传递给reducer。对reducer的每次调用都会为特定公司提供一个Iterable间隙值。遍历数据以生成平均值,并以"company"one_answers"average_map"的形式写入键值对。
如果最初的访问量太大,我们可以讨论让hadoop用一些自定义比较器为您进行排序。