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. windows上编译boost库

    要用xx库,编译boost时就指定--with-xx.例如: # 下载并解压boost_1.58 # 进入boost_1.58目录 bjam.exe toolset=msvc-14.0 --build ...

  2. 一脸懵逼学习Nginx及其安装,Tomcat的安装

    1:Nginx的相关概念知识: 1.1:反向代理: 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到 ...

  3. WebApi接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...

  4. scrapy下载图片报[scrapy.downloadermiddlewares.robotstxt] DEBUG: Forbidden by robots.txt:错误

    本文转自:http://blog.csdn.net/zzk1995/article/details/51628205 先说结论,关闭scrapy自带的ROBOTSTXT_OBEY功能,在setting ...

  5. 007 numpy数组文件的存取

    不知道这个有没有用,都整理了一番. 一:数组以二进制格式进行存储 1.说明 np.save与np.load是读写磁盘数组数据的两个重要函数. 默认情况下,数组以压缩的原始二进制格式保存在扩展名为npy ...

  6. 基于PySpark的网络服务异常检测系统 阶段总结(二)

    在上篇博文中介绍了网络服务异常检测的大概,本篇将详细介绍SVDD和Isolation Forest这两种算法 1. SVDD算法 SVDD的英文全称是Support Vector Data Descr ...

  7. Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑

    Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑 前言 基于 python27 的 pyc 很容易被反编译,于是想到了pyd,加速运行,安全保护 必要准备 安装 ...

  8. Java中CardLayout布局方式的应用

    import java.awt.CardLayout; import java.awt.Color; import java.awt.Container; import javax.swing.JBu ...

  9. CentOS 通过yum在线安装MySQL5.7

    CentOS 通过yum在线安装MySQL5.7 Step1: 检测系统是否自带安装mysql # yum list installed | grep mysql Step2: 删除系统自带的mysq ...

  10. windows下编译php7图形库php_ui.dll

    CSDN博客 具有图形化编程才有意思,这几天看到了php ui 图形扩展,只是现在只能下载php 7.1的 本次教程编译php7.2.6的 php ui 要是linux下编译起来比较简单 但是 win ...