Map Reduce 常见查询的简单得分汇总

0 投票
1 回答
518 浏览
提问于 2025-04-17 17:01

我的一个映射器生成了一些日志,这些日志分散在像 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))

撰写回答