hadoop实现倒排索引

本文用hadoop实现倒排索引算法,用基本的分两步完成,不使用combine

第一步

读入文档,统计文档中各个单词的个数,与word count类似,但这里把word-filename组合起来作为一个key,并把中间结果写到磁盘中

InverseIndexStepTwo.java

package postlisting;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.StringUtils; import java.io.IOException; /**
* 倒排索引步骤一,先做word count,不过现在的key是word-filename
*/
public class InverseIndexStepOne {
public static class StepOneMapper extends Mapper<LongWritable, Text, Text, LongWritable>{
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
// 切分出各个单词
String[] fields = line.split(" ");
// 获取文件切片
FileSplit inputsplit = (FileSplit)context.getInputSplit();
// 获取文件名
String filename = inputsplit.getPath().getName();
// 计数hello-->a.txt 1
for(String field: fields){
context.write(new Text(field+"-->"+filename), new LongWritable(1));
}
}
} public static class StepOneReducer extends Reducer<Text, LongWritable, Text, LongWritable>{
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
long counter = 0;
for (LongWritable value: values){
counter += value.get();
}
context.write(key, new LongWritable(counter));
}
} public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); job.setJarByClass(InverseIndexStepOne.class); job.setMapperClass(StepOneMapper.class);
job.setReducerClass(StepOneReducer.class); job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class); // 检查输出文件夹是否已存在,如果存在先删除
// 本地测试
Path output = new Path("res/words/output/step1");
FileSystem fs = FileSystem.get(conf);
if(fs.exists(output)){
fs.delete(output, true);
}
FileInputFormat.setInputPaths(job, new Path("res/words/input/"));
FileOutputFormat.setOutputPath(job, output);
System.out.println(job.waitForCompletion(true));
}
}

输出结果

hello-->a.txt	2
hello-->b.txt 2
hello-->c.txt 2
jerry-->a.txt 1
jerry-->b.txt 3
jerry-->c.txt 1
tom-->a.txt 3
tom-->b.txt 1
tom-->c.txt 1

第二步

读取上一步的中间结果,解析并合并

InverseIndexStepOne.java

package postlisting;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException; public class InverseIndexStepTwo {
public static class StepTwoMapper extends Mapper<LongWritable, Text, Text, Text> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
// hello-->a.txt 1
String[] fields = line.split("\t");
String[] wordAndFileName = fields[0].split("-->");
String word = wordAndFileName[0];
String fileName = wordAndFileName[1];
long count = Long.parseLong(fields[1]);
// <hello, a.txt-->3>
context.write(new Text(word), new Text(fileName + "-->" + count));
}
} public static class StepTwoReducer extends Reducer<Text, Text, Text, Text>{
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
// 拿到的数据<hello, a.txt-->3, a.txt-->4,...>
StringBuilder result = new StringBuilder();
for (Text value:values){
result.append(" ").append(value);
}
context.write(key, new Text(result.toString()));
}
} public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); job.setJarByClass(InverseIndexStepTwo.class); job.setMapperClass(StepTwoMapper.class);
job.setReducerClass(StepTwoReducer.class); job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); // 检查输出文件夹是否已存在,如果存在先删除
Path output = new Path("res/words/output/step2");
FileSystem fs = FileSystem.get(conf);
if(fs.exists(output)){
fs.delete(output, true);
}
FileInputFormat.setInputPaths(job, new Path("res/words/output/step1/"));
FileOutputFormat.setOutputPath(job, output);
System.out.println(job.waitForCompletion(true));
}
}

输出结果

hello	 c.txt-->2 b.txt-->2 a.txt-->2
jerry c.txt-->1 b.txt-->3 a.txt-->1
tom c.txt-->1 b.txt-->1 a.txt-->3

小结

虽然用combine可以节省代码,但感觉分开写更加灵活,写个shell脚本组织一下就好,Map Reduce的强大之处也在与它的自由组合。

hadoop实现倒排索引的更多相关文章

  1. Hadoop之倒排索引

    前言: 从IT跨度到DT,如今的数据每天都在海量的增长.面对如此巨大的数据,如何能让搜索引擎更好的工作呢?本文作为Hadoop系列的第二篇,将介绍分布式情况下搜索引擎的基础实现,即“倒排索引”. 1. ...

  2. hadoop学习笔记之倒排索引

    开发工具:eclipse 目标:对下面文档phone_numbers进行倒排索引: 13599999999 1008613899999999 12013944444444 13800138000137 ...

  3. hadoop倒排索引

    1.前言 学习hadoop的童鞋,倒排索引这个算法还是挺重要的.这是以后展开工作的基础.首先,我们来认识下什么是倒拍索引: 倒排索引简单地就是:根据单词,返回它在哪个文件中出现过,而且频率是多少的结果 ...

  4. Hadoop 倒排索引

    倒排索引是文档检索系统中最常用的数据结构,被广泛地应用于全文搜索引擎.它主要是用来存储某个单词(或词组)在一个文档或一组文档中存储位置的映射,即提供了一种根据内容来查找文档的方式.由于不是根据文档来确 ...

  5. Hadoop学习笔记(8) ——实战 做个倒排索引

    Hadoop学习笔记(8) ——实战 做个倒排索引 倒排索引是文档检索系统中最常用数据结构.根据单词反过来查在文档中出现的频率,而不是根据文档来,所以称倒排索引(Inverted Index).结构如 ...

  6. Hadoop案例(四)倒排索引(多job串联)与全局计数器

    一. 倒排索引(多job串联) 1. 需求分析 有大量的文本(文档.网页),需要建立搜索索引 xyg pingping xyg ss xyg ss a.txt xyg pingping xyg pin ...

  7. hadoop学习第三天-MapReduce介绍&&WordCount示例&&倒排索引示例

    一.MapReduce介绍 (最好以下面的两个示例来理解原理) 1. MapReduce的基本思想 Map-reduce的思想就是“分而治之” Map Mapper负责“分”,即把复杂的任务分解为若干 ...

  8. Hadoop实战-MapReduce之倒排索引(八)

    倒排索引 (就是key和Value对调的显示结果) 一.需求:下面是用户播放音乐记录,统计歌曲被哪些用户播放过 tom        LittleApple jack       YesterdayO ...

  9. Hadoop MapReduce编程 API入门系列之倒排索引(二十四)

    不多说,直接上代码. 2016-12-12 21:54:04,509 INFO [org.apache.hadoop.metrics.jvm.JvmMetrics] - Initializing JV ...

随机推荐

  1. ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN DESC)函数的使用

    ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN DESC)函数的作用是指定COLUMN(列)进行分区,在分区内指定COLUMN(列)进行排序 ...

  2. SQL Server Profiler的简单使用

    SQL Server Profiler可以检测在数据上执行的语句,特别是有的项目不直接使用sql语句,直接使用ORM框架的系统处理数据库的项目,在调试sql语句时,给了很大的帮助. 之前写了使用SQL ...

  3. Json对象处理.将对象处理成dic数组.

    var parser = new JsonConfigurationFileParser();var dict = parser.Parse("json"); using Newt ...

  4. 使用Github Pages和Hexo构建个人博客

    Github Pages可以创建免费的静态站点,支持自带主题.支持自制页面等,并且可以使用Jekyll或者Hexo等静态博客框架进行管理. 独立博客是博客园等博客平台之外的一个良好补充,相比使用虚拟主 ...

  5. 【Ruby】Mac gem的一些坑

    前言 自上一次升级MacOS系统后出现jekyll无法构建的问题,当时处理半天.谁知道最近又升级了MacOS,荒废博客多时,今天吝啬写了一篇准备发布,构建报错,问题重新.还是记录下,以防下次升级出问题 ...

  6. 基于jquery的页面分屏切换模板

    闲来无事,搞了个页面的分屏效果,先来看下效果: 出于可自定义宽高的目的,屏幕分块由CSS控制,由js控制估计等分模块效果一般. 程序相关说明: HTML结构: <div class=" ...

  7. HTTP虚拟主机

    Ps:http-2.4版本 [root@localhost ~]# tar zxvf httpd-2.4.23.tar.gz -C /usr/src/ [root@localhost ~]# cd / ...

  8. HTML中鼠标滚轮事件onmousewheel

    IE/Opera属于同一类型,使用attachEvent即可添加滚轮事件. /*IE注册事件*/ if(document.attachEvent){ document.attachEvent('onm ...

  9. sql对于字符串的处理

  10. M. Subsequence 南昌邀请赛

    链接: https://nanti.jisuanke.com/t/38232 先给出一个s母串 然后给出n个子串 判断是否为母串的子序列 3000ms  2993ms过的.... 蒻鲫的代码: 建立表 ...