例如,我们需要在属性ID上做关系R和关系S的自然连接。在Map阶段对于每一条R和S中的记录r,我们把它的ID的值作为键,其余属性的值以及R(S中的记录为S的名称)的名称作为值输出出去。在Reduce阶段我们则将统一键中所有的值,根据他们的来源(RR和S)分为两组做笛卡尔乘积然后将得到的结果输出出去。
Map端首先从用户获得需要连接的属性的列号,谈后对于每一条记录,以相应属性上的值作为键,剩余的树形作为值发送键值对到Reduce端。
例如以上面的关系R和关系S为例。关系R中ID为1的记录会以键值对(1,(relation,张小雅,20,91))发射出去,而关系S中ID为1的记录会以键值对(1,(relationS,女,165))发射出去,这里在值前面添加来源关系的名称是为例Reduce端能够辨别键值对的来源。在Reduce端ID为1,的值有两个,按照它们的来源分组为两组(张小雅,20,91)和(女,165),然后将这两组进行笛卡尔乘积并添加上ID(也就是键)作为新的值发出去,这里新的值为:(1,张小雅,20,91,女,165)。
自然连接操作Map端的实现代码如下:
//自然连接操作Map端的实现代码 start
public static class NaturalJoinMap extends Mapper<Text, BytesWritable, Text,Text>{
private int col;
//获得用户设置的连接属性的列号
protected void setup(Context context) throws IOException,InterruptedException {
col =context.getConfiguration().getInt("col", 0);
}
protected void map(Text relationName,BytesWritable content, Context context) throws IOException ,InterruptedException {
String[]records = newString(content.getBytes(),"UTF-8").split("\\n");
for (int i = 0; i < records.length; i++) {
RelationArecord = newRelationA(records);
context.write(new Text(record.getCol(col)), newText(relationName.toString() + " " + record.getValueExcept(col)));
}
}
}
Map端首先从用户获得需要连接的属性的列号,谈后对于每一条记录,以相应属性上的值作为键,剩余的树形作为值发送键值对到Reduce端。
Reduce端的实现代码如下:
//Reduce端的实现代码如下
public static class NaturalJoinRduce extends Reducer<Text, Text,Text, NullWritable>{
//存储关系名称
private String relationNameA;
protected void setup(Context context) throws IOException,InterruptedException {
relationNameA =context.getConfiguration().get("relationNameA");
}
protected void reduce(Text key,java.lang.Iterable<Text> values, Context context) throws IOException,InterruptedException {
ArrayList<Text>setR = newArrayList<Text>();
ArrayList<Text>setS = newArrayList<Text>();
//按照来源分为两组,然后做笛卡尔乘积
for (Text val : values) {
String[]recordInfo = val.toString().split(" ");
if(recordInfo[0].equalsIgnoreCase(relationNameA)){
setR.add(new Text(recordInfo[1]));
}else{
setS.add(new Text(recordInfo[1]));
}
}
for (int i = 0; i <setR.size(); i++) {
for (int j = 0; j <setS.size(); j++) {
Textt = newText(setR.get(i).toString() + "," + key.toString() + "," + setS.get(j).toString());
context.write(t,NullWritable.get());
}
}
}
}