Hadoop学习笔记(8)

——实战 做个倒排索引

倒排索引是文档检索系统中最常用数据结构。根据单词反过来查在文档中出现的频率,而不是根据文档来,所以称倒排索引(Inverted Index)。结构如下:

这张索引表中, 每个单词都对应着一系列的出现该单词的文档,权表示该单词在该文档中出现的次数。现在我们假定输入的是以下的文件清单:

T1 : hello world hello china

T2 : hello hadoop

T3 : bye world bye hadoop bye bye

输入这些文件,我们最终将会得到这样的索引文件:

bye    T3:4;

china    T1:1;

hadoop    T2:1;T3:1;

hello    T1:2;T2:1;

world    T1:1;T3:1;

接下来,我们就是要想办法利用hadoop来把这个输入,变成输出。从上一章中,其实也就是分析如何将hadoop中的步骤个性化,让其工作。整个步骤中,最主要的还是map和reduce过程,其它的都可称之为配角,所以我们先来分析下map和reduce的过程将会是怎样?

首先是Map的过程。Map的输入是文本输入,一条条的行记录进入。输出呢?应该包含:单词、所在文件、单词数。 Map的输入是key-value。 那这三个信息谁是key,谁是value呢? 数量是需要累计的,单词数肯定在value里,单词在key中,文件呢?不同文件内的相同单词也不能累加的,所以这个文件应该在key中。这样key中就应该包含两个值:单词和文件,value则是默认的数量1,用于后面reduce来进行合并。

所以Map后的结果应该是这样的:

Key value

Hello;T1 1

Hello:T1 1

World:T1 1

China:T1 1

Hello:T2 1

即然这个key是复合的,所以常归的类型已经不能满足我们的要求了,所以得设置一个复合健。复合健的写法在上一章中描述到了。所以这里我们就直接上代码:

  1. public static class MyType implements WritableComparable<MyType>{
  2.       public MyType(){
  3.       }
  4.       private String word;
  5.       public String Getword(){return word;}
  6.       public void Setword(String value){ word = value;}
  7.       private String filePath;
  8.       public String GetfilePath(){return filePath;}
  9.       public void SetfilePath(String value){ filePath = value;}
  10.       @Override
  11.       public void write(DataOutput out) throws IOException {
  12.          out.writeUTF(word);
  13.          out.writeUTF(filePath);
  14.       }
  15.       @Override
  16.       public void readFields(DataInput in) throws IOException {
  17.          word = in.readUTF();
  18.          filePath = in.readUTF();
  19.       }
  20.       @Override
  21.       public int compareTo(MyType arg0) {
  22.             if (word != arg0.word)
  23.                return word.compareTo(arg0.word);
  24.          return filePath.compareTo(arg0.filePath);
  25.       }
  26. }

有了这个复合健的定义后,这个Map函数就好写了:

  1. public static class InvertedIndexMapper extends
  2.          Mapper<Object, Text, MyType, Text> {
  3.       public void map(Object key, Text value, Context context)
  4.             throws InterruptedException, IOException {
  5.          FileSplit split = (FileSplit) context.getInputSplit();
  6.          StringTokenizer itr = new StringTokenizer(value.toString());
  7.          while (itr.hasMoreTokens()) {
  8.             MyType keyInfo = new MyType();
  9.             keyInfo.Setword(itr.nextToken());
  10.             keyInfo.SetfilePath(split.getPath().toUri().getPath().replace("/user/zjf/in/", ""));
  11.             context.write(keyInfo, new Text("1"));
  12.          }
  13.       }
  14.    }

注意:第13行,路径是全路径的,为了看起来方便,我们把目录替换掉,直接取文件名。

有了Map,接下来就可以考虑Recude了,以及在Map之后的Combine。Map的输出的Key类型是MyType,所以Reduce以及Combine的输入就必须是MyType了。

如果直接将Map的结果送到Reduce后,发现还需要做大量的工作来将Key中的单词再重排一下。所以我们考虑在Reduce前加一个Combine,先将数量进行一轮合并。

这个Combine将会输入下面的值:

Key value

bye    T3:4;

china    T1:1;

hadoop    T2:1;

hadoop    T3:1;

hello    T1:2;

hello    T2:1;

world    T1:1;

world    T3:1;

代码如下:

  1. public static class InvertedIndexCombiner extends
  2.          Reducer<MyType, Text, MyType, Text> {
  3.       public void reduce(MyType key, Iterable<Text> values, Context context)
  4.             throws InterruptedException, IOException {
  5.          int sum = 0;
  6.          for (Text value : values) {
  7.             sum += Integer.parseInt(value.toString());
  8.          }
  9.          context.write(key, new Text(key.GetfilePath()+ ":" + sum));
  10.       }
  11.    }

有了上面Combine后的结果,再进行Reduce就容易了,只需要将value结果进行合并处理:

  1. public static class InvertedIndexReducer extends
  2.          Reducer<MyType, Text, Text, Text> {
  3.       public void reduce(MyType key, Iterable<Text> values, Context context)
  4.             throws InterruptedException, IOException {
  5.          Text result = new Text();
  6.          String fileList = new String();
  7.          for (Text value : values) {
  8.             fileList += value.toString() + ";";
  9.          }
  10.          result.set(fileList);
  11.          context.write(new Text(key.Getword()), result);
  12.       }
  13.    }

    经过这个Reduce处理,就得到了下面的结果:

bye    T3:4;

china    T1:1;

hadoop    T2:1;T3:1;

hello    T1:2;T2:1;

world    T1:1;T3:1;

最后,MapReduce函数都写完后,就可以挂在Job中运行了。

  1. public static void main(String[] args) throws IOException,
  2.          InterruptedException, ClassNotFoundException {
  3.       Configuration conf = new Configuration();
  4.       System.out.println("url:" + conf.get("fs.default.name"));
  5.       Job job = new Job(conf, "InvertedIndex");
  6.       job.setJarByClass(InvertedIndex.class);
  7.       job.setMapperClass(InvertedIndexMapper.class);
  8.       job.setMapOutputKeyClass(MyType.class);
  9.       job.setMapOutputValueClass(Text.class);
  10.       job.setCombinerClass(InvertedIndexCombiner.class);
  11.       job.setReducerClass(InvertedIndexReducer.class);
  12.       job.setOutputKeyClass(Text.class);
  13.       job.setOutputValueClass(Text.class);
  14.       Path path = new Path("out");
  15.       FileSystem hdfs = FileSystem.get(conf);
  16.       if (hdfs.exists(path))
  17.          hdfs.delete(path, true);
  18.       FileInputFormat.addInputPath(job, new Path("in"));
  19.       FileOutputFormat.setOutputPath(job, new Path("out"));
  20.       job.waitForCompletion(true);
  21. }

注:这里为了调试方便,我们把in和out都写死,不用传入执行参数了,并且,每次执行前,判断out文件夹是否存在,如果存在则删除。

转载于:https://www.cnblogs.com/zjfstudio/p/3913549.html

Hadoop学习笔记(8) ——实战 做个倒排索引相关推荐

  1. Hadoop学习笔记—18.Sqoop框架学习

    Hadoop学习笔记-18.Sqoop框架学习 一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据 ...

  2. Hadoop学习笔记(1) ——菜鸟入门

     Hadoop学习笔记(1) --菜鸟入门 Hadoop是什么?先问一下百度吧: [百度百科]一个分布式系统基础架构,由Apache基金会所开发.用户能够在不了解分布式底层细节的情况下.开发分布式 ...

  3. Hadoop学习笔记(1)

    原文:http://www.cnblogs.com/zjfstudio/p/3859704.html Hadoop学习笔记(1) --菜鸟入门 Hadoop是什么?先问一下百度吧: [百度百科]一个分 ...

  4. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    Hadoop学习笔记-20.网站日志分析项目案例(一)项目介绍 网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edis ...

  5. Hadoop学习笔记—4.初识MapReduce

    一.神马是高大上的MapReduce MapReduce是Google的一项重要技术,它首先是一个 编程模型 ,用以进行大数据量的计算.对于大 数据量的计算,通常采用的处理手法就是并行计算.但对许多开 ...

  6. Hadoop学习笔记—16.Pig框架学习

    Hadoop学习笔记-16.Pig框架学习 一.关于Pig:别以为猪不能干活 1.1 Pig的简介 Pig是一个基于Hadoop的大规模数据分析平台,它提供的SQL-LIKE语言叫Pig Latin, ...

  7. Hadoop学习笔记(四)HDFS部分下

    Hadoop学习笔记(四)HDFS部分下 一.HDFS 的数据流 1.1 HDFS的写数据流程 客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,Nam ...

  8. Redis学习笔记(实战篇)(自用)

    Redis学习笔记(实战篇)(自用) 本文根据黑马程序员的课程资料与百度搜索的资料共同整理所得,仅用于学习使用,如有侵权,请联系删除 文章目录 Redis学习笔记(实战篇)(自用) 1.基于Sessi ...

  9. Hadoop学习笔记一 简要介绍

    Hadoop学习笔记一 简要介绍 这里先大致介绍一下Hadoop.     本文大部分内容都是从官网Hadoop上来的.其中有一篇介绍HDFS的pdf文档,里面对Hadoop介绍的比较全面了.我的这一 ...

最新文章

  1. html实时显示log,websocketd 实现浏览器查看服务器实时日志
  2. Java性能优化(12):最小化类和成员可访问能力
  3. php调用dll函数,[转载]matlab调用DLL中的函数
  4. 传智播客全栈_播客:从家庭学生到自学成才的全栈开发人员
  5. excel营销数据分析宝典 pdf_你见过最漂亮的 Excel 表格什么样?
  6. 异步请求引发的Chrome死锁
  7. python数组和列表的区别_JS数组方法与python列表方法的比较
  8. Python的Base64编码图片(转载)
  9. Resteasy配置及其使用
  10. 阿里云-个人建网站从0到精通(二)-快速搭建网站
  11. IT软件工程师工作内容
  12. 计算机管理内默认共享,Win10共享默认在哪里关闭 清除默认共享哪种方法比较彻底...
  13. 国家级精品课程 电子资源 网址
  14. 解决Chrome浏览器变慢
  15. epoll反应堆及ET模式下的EPOLLOUT学习总结
  16. 精通RPM之--制作篇(上) 原作:雨亦奇 赵建利
  17. 【CF833D】Red-Black Cobweb
  18. dsf5.0没登录显示登录弹框
  19. HTML设计网页之网页头部
  20. WebSocket connection to 'ws://localhost:8080/shipinceshi/video/1546871583183

热门文章

  1. Day 14 知识点串讲 下
  2. Linux tomcat日志分割按天分割
  3. PgwSlideshow-基于Jquery的图片轮播插件
  4. mysql的limit使用方法
  5. Spring使用Quartz配置调度事务
  6. 作幼儿教育软件的感受(2005-05-09)
  7. 怎么样才能让自己自律起来_一个人如何才能高度自律(深度好文)
  8. hibernate中一对多关系的映射
  9. ListView详解 (ListView图文混排)
  10. 编程范式,程序员的编程世界观