例如,我有两个文件,A和B.它们都是文本文件。
A包含一行文字,如下所示:
I'm A
B包含三行文字:
I'm B1
I'm B2
I'm B3
我的例外是将A的唯一一行添加到B的每一行的前面,结果将是:
I'm A I'm B1
I'm A I'm B2
I'm A I'm B3
对我来说,困难的部分是如何理解MapReduce作业的参数。在传统的函数中,我可以让A和B成为两个参数,然后在我的规则中合并它们。一些像这样的伪代码:
// Two parameters, A and B
public void merge(File A, File B) {
String lineA = A.firstLine;
for (Each lineB in B) {
String result = lineA + " " + lineB;
File.wirte(result, "ResultFile", appended);
}
}
但是在MapReduce阶段,没有"传统参数",例如:
public void map(LongWritable key, Text value, Context context) {
String line = value.toString();
try {
context.write(new Text(line), new Text(""));
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
据我所知,上面的代码会逐行读取文件,使用每一行作为键并将值设置为空,然后将键值对写入文件。
但同样,上面的映射器代码没有传统的参数,我不知道如何执行合并字符串的逻辑,并将结果写出来。
以下是我现在想到的伪代码,我的设计是正确的还是我的方向错误?我该如何设计MapReduce作业?一些示例代码将非常有用!
// I think I should pass in two Files
// So I can merge the line of them
public void map(File A, File B, Context context) {
String key = A.firstLine();
for (each LineB in B) {
String value = key + " " + lineB;
}
try {
context.write(new Text(""), value);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
答案 0 :(得分:0)
这是一个交叉连接 - 将A中的每条记录连接到B中的每条记录。幸运的是,这是一个很好的MapReduce设计模式。
解决方案取决于数据集的大小。如果A或B可以适合记忆,那么你很幸运。只需将它们中的任何一个添加到DistributedCache中,只将另一个读入映射器。你甚至不需要减速器!
如果两个数据集都很大,那么您的解决方案必须涉及编写自定义输入拆分,以确保每组数据输出足够的时间以匹配来自另一组的所有块。请参阅Cross product in MapReduce - 此示例也包含在MapReduce设计模式一书中。