Map Reduce 常见查询的简单得分汇总
我的一个映射器生成了一些日志,这些日志分散在像 part-0、part-1、part-2 这样的文件里。每个文件里都有一些查询和与这些查询相关的数据:
part-0
q score
1 ben 10 4.01
horse shoe 5.96
...
part-1
1 ben 10 3.23
horse shoe 2.98
....
and so on for part-2,3 etc.
现在,查询 q,也就是上面的 "1 ben 10",出现在 part-1、part-2 等文件中。
我需要写一个 MapReduce 阶段,来收集相同的查询并把它们的分数加起来。
我的映射器函数可以简单地返回输入数据,而在归约阶段我会完成这个任务。
输出结果将是:
q aggScore
1 ben 10 7.24
horse shoe 8.96
...
这看起来是个简单的任务,但我现在不知道该怎么开始(虽然读了很多,但还是没法进行下去)。我能想到的是一个通用的算法问题,首先收集相同的查询,然后把它们的分数加起来。
如果能给我一些关于 Python 解决方案或算法(MapReduce)的提示,我会非常感激。
1 个回答
1
这是一个MapReduce的解决方案:
输入的文件:每个输入文件(比如part-0、part-1、part-2等)可以被单独的map任务处理。
对于输入文件中的每一行,Mapper会输出一个<q,aggScore>
。如果在一个文件中同一个查询有多个分数,Map会把它们加起来;如果我们知道每个查询在每个文件中只出现一次,那么map可以直接把每一行的内容作为<q,aggScore>
输出。
Reducer的输入格式是<q,list<aggScore1,aggScore2,...>
。Reducer的操作和大家熟悉的MapReduce示例wordcount
类似。如果你在使用Hadoop,可以用以下方法来实现Reducer。
public void reduce(Text q, Iterable<IntWritable> aggScore, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : aggScore) {
sum += val.get();
}
context.write(q, new IntWritable(sum));
}
这个方法会把特定q
的所有aggScores
加起来,给你想要的输出。Reducer的Python代码大概是这样的(这里q
是键,而aggScores
的列表是值):
def reduce(self, key, values, output, reporter):
sum = 0
while values.hasNext():
sum += values.next().get()
output.collect(key, IntWritable(sum))