链接不同来源的数据:
Reduce侧的联结、DATAJOIN软件包实现联结、
DATAJOIN软件包实现了联结的数据流
其中有3个可供继承和具体化的抽象类:DataJoinMapperBase、DateJoinReducerBase和TaggedMapOutput
在数据流中mapper输出的包带有一个(组)键和一个被标签记录的值。
datajoin包指定(组)键为Text类型,而值(即被标记的记录)为TaggedOutput类型。
TaggedMapOutput是一种用Text标签封装记录的数据类型。它具体实现了getTag()和
setTag(Text tag)方法,并指定抽象方法getDate()。
没有明确要求我们的子类必须包含setData()方法,但我们必须将记录数据传入。
作为mapper的输出,TaggedMapOutput必须为Writable类型。
所以,我们的子类必须实现readFields()和write()方法。
//用于处理所有Writable的记录类型。
public static class TaggedWritable extends TaggedMapOutput{
}
在联结操作的数据流中,mapper的主要功能时封装一个记录,
使它与其他有相同联结键的记录都被送到相同的reducer。
DataJoinMapperBase执行所有的封装,但这个类为我们的子类指定了3个
可以填充的抽象方法:
protected abstract Text generateInputTag(String inputFile);
//map任务开始时被调用,为这个map任务所处理的所有记录指定一个全局的标签。
//Text类型,我们使用记录的文件名来调用generateInputTag()。
//mapper将接收处理文件的文件名(以字符串形式)作为generateInputTag()的参数。
protected abstract TaggedMapOutput generateTaggedMapOutput(Object value);
protected abstract Text generateGroupKey(TaggedMapOutput aRecord);
我们正在使用这个标签来标识数据源,我们的文件名又是用来反映数据源的
generateInputTag()写为
如果数据源横跨几个文件(part-0000、part-0001等),
不用完整的文件名作为标签,而是用前缀的方法是:
eg:标签(数据源)可以为短画线(-)前的文件名。
protected Text generateInputTag(String inputFile){
}
之后generateInputTag()的结果存放在DataJoinMapperClass对象的变量inputTag中
如果想再次提及它可把文件名存入DataJoinMapperBase的变量inputFile中。
-------
完成mapper函数的初始化后,为每个记录调用DataJoinMapperBase的map()。
之后它再实现后边的抽象方法。
public void map(Object key,Object value,
{
}
TaggedMapOutput具体实现为TagWritable。
GenerateTaggedMapOutput()方法可以返回一个带有任何我们所想要的Text标签
的TaggedWritable。
原则上,在同一文件中,不同的记录可以用不同的标签。
标准情况下,希望标签代表一个数据源,它由早先已由generateInputTag()
计算好并放在this.inputTag中。
protected TaggedMappedOutput generateTaggedMapOutput(Object value){
}
GenerateGroupKey()方法取得被标记的记录(TaggedMapOutput类型),
并返回用作联结的组键。
之后,我们解开有标签的记录,并取CSV格式的值的第一个域作为联结键。
protected Text generateGroupKey(TaggedMapOutput aRecord){
}
用户能够指定哪些字段为联结键,以及是否记录的分隔符可以为逗号之外的一些字符。
DataJoinMapperBase是一个简单的类,而mapper代码的大部分在我们的子类中。
DataJoinReducerBase是datajoin软件包的核心,它通过执行一个完整的外部联结,
简化编程。
我们的reducer子类只是必须实现combine()方法来筛选掉不需要的组合,以获取所需
的联结操作(内部联结,左外部联结的等)。
在combine()方法中,我们将合并结果格式化为合适的输出格式。
我们为combine()方法提供一个有相同联结键(组)的标记记录的交叉乘的合并。
每个合并的记录要么为2个(意味着在每个有组键的数据源中至少有一个记录),
要么为1个(意味着仅有一个数据源有该联结键)。
protected abstract TaggedMapOutput combine(Object[] tags,Object[] values);
一个合并结果由一个标签数组和一个值的数组来表示。
这两个数组的大小必须保证相同,且等于合并结果中被标记记录的个数。
合并结果中第一个被标记的记录表示为tags[0]和values[0],
第2个为tags[1]和values[1],以此类推。标签是按顺序排列的。
由于标签与数据源对应,在两个数据源相连接的典型情况下,
combine()的标签数组长度不会超过2。
eg:
tags = {"Customers","Orders"};
values = {"3,Jose Madriz,281-330-8004","A,12.95,02-Jun-2008"};
//连个reduce侧连接数据的内联结
public class DataJoin extends Configured implements Tool {
}