分享

Reduce Join的一个问题,输出结果不对,简单的例子

爱动的蜗牛 发表于 2015-11-4 13:30:09 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 3 11327
上次发了一次,感觉没说清楚,Alkaloid0515给了建议,收获很大,但是还是没找出错在哪,所以再发一次
这有一个reduce join的问题,输入文件是一个表,表的内容如下(分割符是Tab键),每一行内容分别是child和parent的名字
child        parent
Jone        Lucy
Jone        Jack
Tom        Lucy
Tom        Jack
Lucy        Mary
Lucy        Ben
Jack        Alice
Jack        Jesse
Terry        Alice
Terry        Jesse
Philip        Terry
要求输出grandchild        grandparent表。

我的想法是将这个表写成两份,一个是左表,加标志位“2”表示。另一个是右表,加标志位“1”表示。
在map阶段,左表用parent的名字作为key,右表用child的名字作为key。在map输出后的shuffle阶段,
会将相同key的value的值连接在一个List集合中,而两表join发生在reduce中,join的原则是:对于同一个key,
如果同时存在于左右表中,即可合并。
例如:对于左表“2 Jone        Lucy”和右表“1 Lucy  Mary”,
因为key=Lucy,同时存在于两个表中,
即Lucy是Jone的parent,还是Mary的child,自然Jone是Mary是grandchild,所以这两个表符合join的原则。
把这个grandchild和grandparent名字存储起来,最后做卡迪尔积
程序如下:
Mapper函数:
  1. public class STJoinMapper extends Mapper<LongWritable, Text, Text, Text>{
  2.         //对child        parent字段不处理
  3.         private LongWritable begin=new LongWritable(0);
  4.         @Override
  5.         protected void map(LongWritable key, Text value,Context context)
  6.                         throws IOException, InterruptedException {
  7.                 if(key!=begin){
  8.                         String line=value.toString();
  9.                         StringTokenizer strtoken=new StringTokenizer(line, "\t");
  10.                         String childName=new String();
  11.                         String        parentName=new String();
  12.                         if(strtoken.hasMoreTokens()){
  13.                                 childName=strtoken.nextToken();
  14.                                 parentName=strtoken.nextToken();
  15.                                 //分表
  16.                                 context.write(new Text(childName), new Text("1"+" "+childName+" "+parentName));
  17.                                 context.write(new Text(parentName),new Text("2"+" "+childName+" "+parentName));
  18.                         }
  19.                 }
  20.         }
  21. }
复制代码

Reducer函数:
  1. public class STJoinReducer extends Reducer<Text, Text, Text, Text>{
  2.         private boolean        flag=false;
  3.         @Override
  4.         protected void reduce(Text key, Iterable<Text> valueList,Context context) throws IOException,
  5.                         InterruptedException {
  6.                 //输出表头:grandchild        grandparent
  7.                 if(flag==false){
  8.                         context.write(new Text("grandchild"), new Text("grandparent"));
  9.                         flag=true;
  10.                 }
  11.                 ArrayList<String> grandchildList=new ArrayList<String>();
  12.                 ArrayList<String> grandparentList=new ArrayList<String>();
  13.                 for(Text name:valueList){
  14.                         String namestr=name.toString();
  15.                         String[] value=namestr.split(" ");
  16.                         if(value[0].equals("1")){
  17.                                 grandchildList.add(value[1]);
  18.                                 continue;
  19.                         }
  20.                         if(value[0].equals("2")){
  21.                                 grandparentList.add(value[2]);
  22.                                 continue;
  23.                         }
  24.                 }
  25.                 //如果只有左表或者只有右表,则不join,否则就求卡迪尔积,输出grandchild        grandparent表
  26.                 if((!grandchildList.isEmpty())&&(!grandparentList.isEmpty())){
  27.                         for(String child:grandchildList){
  28.                                 for(String parent:grandparentList){
  29.                                         context.write(new Text(child), new Text(parent));
  30.                                 }
  31.                         }
  32.                 }
  33.         }
  34. }
复制代码



在伪分布式上跑问题,但是结果错的离谱,可能是逻辑错误,没有找不来

已有(3)人评论

跳转到指定楼层
arsenduan 发表于 2015-11-4 16:31:10
下面标了注释,修改下代码
这里错误,如果左连,只输出左表,如果右连只输出右表,下面只是简单的输出,而不是再次笛卡尔积,所以去掉一个for循环
public class STJoinReducer extends Reducer<Text, Text, Text, Text>{
        private boolean        flag=false;
        @Override
        protected void reduce(Text key, Iterable<Text> valueList,Context context) throws IOException,
                        InterruptedException {
                //输出表头:grandchild        grandparent
                if(flag==false){
                        context.write(new Text("grandchild"), new Text("grandparent"));
                        flag=true;
                }
                ArrayList<String> grandchildList=new ArrayList<String>();
                ArrayList<String> grandparentList=new ArrayList<String>();
                for(Text name:valueList){
                        String namestr=name.toString();
                        String[] value=namestr.split(" ");
                        if(value[0].equals("1")){
                                grandchildList.add(value[1]);
                                continue;
                        }
                        if(value[0].equals("2")){
                                grandparentList.add(value[2]);
                                continue;
                        }
                }
                //如果只有左表或者只有右表,则不join,否则就求卡迪尔积,输出grandchild        grandparent表【这里错误,如果左连,只输出左表,如果右连只输出右表,下面只是简单的输出,而不是再次笛卡尔积,所以去掉一个for循环
                if((!grandchildList.isEmpty())&&(!grandparentList.isEmpty())){
                        for(String child:grandchildList){
                                for(String parent:grandparentList){
                                        context.write(new Text(child), new Text(parent));
                                }
                        }
                }
        }
}



















回复

使用道具 举报

arsenduan 发表于 2015-11-4 16:34:21
这个不错
hadoop mapreduce join代码示例及讲解
http://www.aboutyun.com/thread-12055-1-1.html



回复

使用道具 举报

爱动的蜗牛 发表于 2015-11-4 19:30:10
arsenduan 发表于 2015-11-4 16:34
这个不错
hadoop mapreduce join代码示例及讲解
http://www.aboutyun.com/thread-12055-1-1.html

我这51Job看过这个博客,是大神你写的么?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条