Hadoop单表与多表关联

来源:互联网 发布:it公司 编辑:程序博客网 时间:2024/06/07 06:33

在单表关联和多表关联的应用的时候,需要从数据里面挖掘出信息来进行操作。

例子给出 孩子和父母的表 输出孩子和爷爷的表 数据如下:

亲人表childparenttomjeremtomlucyjeremxdlucyhongtonjackjcterryjcjccy样例输出:

tomxdtomhongtonjackcyterrycy从样例输出,输入可以得出 需要进行单表的链接是自己链接自己,链接的是左表的parent列和右表的child列,结果除去爷孙链接即可。

首先在map阶段将输入数据分割成child和parent之后,需要将parent设为key,child设为value作为左表,而在另一组的child和parent中需要将parent 作为value child作为key,此表作为右表。为了区分左右表,需要将在输出value的时候 附带上左右的区别信息,字符1代表左表 字符2代表右表。map阶段就完成了左表 和右表 ,在shuffle阶段完成链接,reduce接收链接结果,其中key对应的value-list 包含了 对应的关系,取出value值进行分析,将child放入数组1 parent放入数组2 然后进行数组的笛卡尔积得出最后结果。

代码样式入下:

[java] view plaincopy
  1. package reverseIndex;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import java.util.StringTokenizer;  
  6.   
  7. import org.apache.hadoop.conf.Configuration;  
  8. import org.apache.hadoop.fs.Path;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.mapreduce.Job;  
  12. import org.apache.hadoop.mapreduce.Mapper;  
  13. import org.apache.hadoop.mapreduce.Reducer;  
  14. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  15. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  16.   
  17. public class singleJoin {  
  18.     public static int time = 0//  用于表头的输出  
  19.     public static class Map extends Mapper<LongWritable, Text,Text,Text>{  
  20.         public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException{  
  21.             String childName = new String();  
  22.             String parentName = new String();  
  23.             String relationType = new String(); // the flag of left_table right_table  
  24.             //handle line data  
  25.             StringTokenizer itr = new StringTokenizer(value.toString());  
  26.             String[] values = new String[2];  
  27.             int i = 0;  
  28.             while(itr.hasMoreTokens()){  
  29.                 values[i] = itr.nextToken();  
  30.                 i++;  
  31.             }  
  32.             //ignore the title   
  33.             if(values[0].compareTo("child")!=0){  
  34.                 childName = values[0];  
  35.                 parentName = values[1];  
  36.                 //output the left_table  
  37.                 relationType = "1";  
  38.                 context.write(new Text(values[1]), new Text(relationType+"+"  
  39.                                 +childName+"+"+parentName));  
  40.                   
  41.                 //output the right_table  
  42.                 relationType = "2";  
  43.                 context.write(new Text(values[0]),new Text(relationType+"+"  
  44.                             +childName+"+"+parentName));  
  45.             }  
  46.         }  
  47.     }  
  48.     public static class Reduce extends Reducer<Text,Text,Text,Text>{  
  49.          public void reduce(Text key,Iterable<Text>value,Context context) throws IOException, InterruptedException{  
  50.              if(0 == time){  
  51.                  //输出表头   
  52.                  context.write(new Text("grandchild"),new Text("grandparent"));  
  53.                  time++;  
  54.              }  
  55.              int grandchildnum = 0;  
  56.              int grandparentnum = 0;  
  57.              //定义存储grandchild,grandparent的数组  
  58.              String[] grandchild = new String[20];  
  59.              String[] grandparent = new String[20];  
  60.              Iterator<Text> it = value.iterator();  
  61.              while(it.hasNext()){  
  62.                  String record = it.next().toString();  
  63.                  int len = record.length();  
  64.                  int i=2;  
  65.                  if(0==len){  
  66.                      continue;  
  67.                  }  
  68.                  char relationType = record.charAt(0);  
  69.                  String childName = new String();  
  70.                  String parentName = new String();  
  71.                  while(record.charAt(i)!='+'){  
  72.                      childName += record.charAt(i);  
  73.                      i++;  
  74.                  }  
  75.                  i += 1;  
  76.                  while(i<len){  
  77.                      parentName += record.charAt(i);  
  78.                      i++;  
  79.                  }  
  80.                  if('1'==relationType){  
  81.                      grandchild[grandchildnum] = childName;  
  82.                      grandchildnum++;  
  83.                        
  84.                  }  
  85.                  if('2'==relationType){  
  86.                      grandparent[grandparentnum] = parentName;  
  87.                      grandparentnum++;  
  88.                  }  
  89.              }//end while 结束一行数据  
  90.                  if(0!=grandchildnum && 0!=grandparentnum){  
  91.                      for(int m=0;m<grandchildnum;m++){  
  92.                          for(int n=0;n<grandparentnum;n++){  
  93.                              context.write(new Text(grandchild[m]),new Text(grandparent[m]));  
  94.                          }  
  95.                      }  
  96.                  }  
  97.              }//end reduce  
  98.     }//end Reduce  
  99.     public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {  
  100.         // TODO Auto-generated method stub  
  101.         Configuration conf = new Configuration();  
  102.         Job job = new Job(conf,"singleJoin");  
  103.         job.setJarByClass(singleJoin.class);  
  104.         job.setMapperClass(Map.class);  
  105.         job.setReducerClass(Reduce.class);  
  106.           
  107.         job.setOutputKeyClass(Text.class);  
  108.         job.setOutputValueClass(Text.class);  
  109.           
  110.         FileInputFormat.addInputPath(job,new Path(args[0]));  
  111.         FileOutputFormat.setOutputPath(job, new Path(args[1]));  
  112.         System.exit(job.waitForCompletion(true)?0:1);  
  113.     }  
  114. }  

多表链接:输入2个文件 ,一个学生表 包含学生名 和课程编号,另一个是教师名和课程编号 ,输出学生相对应的教师。教师1cy2ld3cy4ld

xd1xyy2lf3zz3输出:xdcyxyyldlfcyzzcy这种多表链接关系 类似于关系型数据库的 多表之间的查询,链接的join语句。

解决方法与上面一致:(左右表)

代码如下:

[java] view plaincopy
  1. package reverseIndex;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import java.util.StringTokenizer;  
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.LongWritable;  
  9. import org.apache.hadoop.io.Text;  
  10. import org.apache.hadoop.mapreduce.Job;  
  11. import org.apache.hadoop.mapreduce.Mapper;  
  12. import org.apache.hadoop.mapreduce.Reducer;  
  13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  15.   
  16. public class multiJoin {  
  17.     public static int time = 0;  
  18.     public static class Map extends Mapper<LongWritable,Text,Text,Text>{  
  19.         public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException{  
  20.             String mapKey = new String();  
  21.             String mapValue = new String();  
  22.             String line = value.toString();  
  23.             String relationType = new String();  
  24.             StringTokenizer it = new StringTokenizer(line);  
  25.             if(line.contains("studentName")||line.contains("courseId")){  
  26.                 return;  
  27.             }  
  28.             int i=0;  
  29.             while(it.hasMoreTokens()){  
  30.                 String token = it.nextToken();  
  31.                 //如果是课程编号在前,就将作为右表,若是人名在前面就是作为左表  
  32.                 if(token.charAt(0)>='0'&&token.charAt(0)<='9'){  
  33.                     mapKey = token;  
  34.                     if(i>0){  
  35.                         relationType = "1";  
  36.                     }else{  
  37.                         relationType = "2";  
  38.                     }  
  39.                     continue;  
  40.                 }  
  41.                 mapValue += token+" ";  
  42.                 i++;  
  43.             }  
  44.             //完后左右表的输出  
  45.             context.write(new Text(mapKey),new Text(relationType+"+"+mapValue));  
  46.         }  
  47.     }  
  48. public static class Reduce extends Reducer<Text,Text,Text,Text>{  
  49.     public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{  
  50.         if(time == 0){  
  51.             context.write(new Text("student"),new Text("teacher"));  
  52.             time++;  
  53.         }  
  54.         int studentnum = 0;  
  55.         int teachernum = 0;  
  56.         String[] student = new String[10];  
  57.         String[] teacher = new String[10];  
  58.         Iterator<Text> it = values.iterator();  
  59.         while(it.hasNext()){  
  60.             String record = it.next().toString();  
  61.             int len = record.length();  
  62.             int i=2;//忽略relationType和+号  
  63.             if(0 == len){  
  64.                 return;  
  65.             }  
  66.             char relationType = record.charAt(0);  
  67.             if('1' == relationType){  
  68.                 student[studentnum] = record.substring(i);  
  69.                 studentnum++;  
  70.             }  
  71.             if('2'==relationType){  
  72.                 teacher[teachernum] = record.substring(i);  
  73.                 teachernum++;  
  74.             }  
  75.         }  
  76.         if(0!=studentnum && 0!=teachernum){  
  77.             for(int m=0;m<studentnum;m++){  
  78.                 for(int n=0;n<teachernum;n++){  
  79.                     context.write(new Text(student[m]), new Text(teacher[n]));  
  80.                 }  
  81.             }  
  82.         }  
  83.           
  84.     }  
  85. }  
  86.     public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {  
  87.         // TODO Auto-generated method stub  
  88.         Configuration conf = new Configuration();  
  89.         Job job = new Job(conf,"multiJoin");  
  90.         job.setJarByClass(multiJoin.class);  
  91.         job.setMapperClass(Map.class);  
  92.         job.setReducerClass(Reduce.class);  
  93.           
  94.         job.setOutputKeyClass(Text.class);  
  95.         job.setOutputValueClass(Text.class);  
  96.           
  97.         FileInputFormat.addInputPath(job,new Path(args[0]));  
  98.         FileOutputFormat.setOutputPath(job, new Path(args[1]));  
  99.         System.exit(job.waitForCompletion(true)?0:1);  
  100.           
  101.     }  
  102. }  
0 0