【Hadoop】MapReduce练习:多job关联实现倒排索引
概述
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。
倒排索引有两种不同的反向索引形式:
一条记录的水平反向索引(或者反向档案索引)包含每个引用单词的文档的列表。
一个单词的水平反向索引(或者完全反向索引)又包含每个单词在一个文档中的位置。
后者的形式提供了更多的兼容性(比如短语搜索),但是需要更多的时间和空间来创建。
现代搜索引擎的索引都是基于倒排索引。相比“签名文件”、“后缀树”等索引结构,“倒排索引”是实现单词到文档映射关系的最佳实现方式和最有效的索引结构。
多Job串联:第一个job产生的输出结果,是第二个job的输入,第二个job执行的前提是获得第一个job的输出结果,第二个job依赖于第一个job,二者是串行执行关系。job1----->job2----->jobn
示例
需求:有大量的文本(文档、网页),需要建立搜索索引。
示例:有a.txt,b.txt,c.txt三个文件,每个文件分别对应一些关键词;
a.txt如下:
map
reduce
MapReduce
index Inverted index
Inverted index
倒排索引
大数据
hadoop MapReduce hdfs
Inverted index
b.txt如下:
hadoop MapReduce hdfs
Inverted index
倒排索引
大数据
map
reduce
MapReduce
c.txt如下:
Inverted index
倒排索引
大数据
hadoop MapReduce hdfs
Inverted index
hadoop MapReduce hdfs
Inverted index
map
reduce
MapReduce
分析如上文件,实现倒排索引并进行多job关联,需要两个job进行解析;
第一个job期望实现如下方式:
Inverted a.txt-->3
Inverted b.txt-->1
Inverted c.txt-->3
MapReduce a.txt-->2
MapReduce b.txt-->2
MapReduce c.txt-->3
hadoop a.txt-->1
hadoop b.txt-->1
hadoop c.txt-->2
hdfs a.txt-->1
hdfs b.txt-->1
hdfs c.txt-->2
index a.txt-->4
index b.txt-->1
index c.txt-->3
map a.txt-->1
map b.txt-->1
map c.txt-->1
reduce a.txt-->1
reduce b.txt-->1
reduce c.txt-->1
倒排索引 a.txt-->1
倒排索引 b.txt-->1
倒排索引 c.txt-->1
大数据 a.txt-->1
大数据 b.txt-->1
大数据 c.txt-->1
第二个job期望实现最后效果:
Inverted b.txt-->1 a.txt-->3 c.txt-->3
MapReduce a.txt-->2 b.txt-->2 c.txt-->3
hadoop a.txt-->1 b.txt-->1 c.txt-->2
hdfs a.txt-->1 b.txt-->1 c.txt-->2
index b.txt-->1 c.txt-->3 a.txt-->4
map a.txt-->1 b.txt-->1 c.txt-->1
reduce a.txt-->1 b.txt-->1 c.txt-->1
倒排索引 a.txt-->1 b.txt-->1 c.txt-->1
大数据 a.txt-->1 b.txt-->1 c.txt-->1
代码详情
IndexOne
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import java.io.IOException;
public class IndexOne { }
class IndexMapperOne extends Mapper<LongWritable, Text, Text, IntWritable> {
String name;
Text tKey = new Text();
IntWritable tValue = new IntWritable();
@Override
protected void setup(Context context) throws IOException, InterruptedException {
//获取文件对象
FileSplit inputSplit = (FileSplit) context.getInputSplit();
//获取文件名
name = inputSplit.getPath().getName();
}
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//获取数据
String line = value.toString();
//切分关键词
String[] words = line.split(" ");
for (String word : words) {
//将关键词和文件名字拼接,作为输出的key
tKey.set(word + "@" + name);
tValue.set(1);
context.write(tKey, tValue);
}
}
}
class IndexReduceOne extends Reducer<Text, IntWritable, Text, Text> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
String line = key.toString();
String[] splits = line.split("@");
StringBuilder builder = new StringBuilder();
int count = 0;
for (IntWritable number : values) {
count += number.get();
}
builder.append(splits[1] + "-->" + count);
context.write(new Text(splits[0]), new Text(builder.toString()));
}
}
IndexTwo
package descIndex;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class IndexTwo {
}
class IndexMapperTwo extends Mapper<LongWritable, Text, Text, Text> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] splits = line.split("\t");
context.write(new Text(splits[0]), new Text(splits[1]));
}
}
class IndexReduceTwo extends Reducer<Text, Text, Text, Text> {
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
StringBuilder builder = new StringBuilder();
for (Text txt : values) {
builder.append(txt + "\t");
}
context.write(key, new Text(builder.toString()));
}
}
JobUtils
package descIndex;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.File;
import java.io.IOException;
public class JobUtils {
private static Configuration conf;
static {
conf = new Configuration();
}
/**
* 获得job实例
* @param paths 输入与输出路径数组
* @param params 类的可变数组
* @return job实例
* @throws IOException
*/
public static Job getJobInstance(String[] paths, Class... params) throws IOException {
Job job = Job.getInstance(conf);
job.setJarByClass(params[0]);
job.setMapperClass(params[1]);
job.setReducerClass(params[2]);
job.setMapOutputKeyClass(params[3]);
job.setMapOutputValueClass(params[4]);
job.setOutputKeyClass(params[5]);
job.setOutputValueClass(params[6]);
FileInputFormat.setInputPaths(job, new Path(paths[0]));
FileOutputFormat.setOutputPath(job, new Path(paths[1]));
return job;
}
}
IndexDriver
package descIndex;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.jobcontrol.ControlledJob;
import org.apache.hadoop.mapreduce.lib.jobcontrol.JobControl;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class IndexDriver {
public static void main(String[] args) throws IOException, InterruptedException {
String[] paths1 = {"F:/index", "F:/outindex1"};
Job job1 = JobUtils.getJobInstance(paths1,IndexDriver.class,IndexMapperOne.class,IndexReduceOne.class
,Text.class,IntWritable.class,Text.class,Text.class);
String[] paths2 = {"F:/outindex1", "F:/outindex2"};
Job job2 = JobUtils.getJobInstance(paths2,IndexDriver.class,IndexMapperTwo.class,IndexReduceTwo.class
,Text.class,Text.class,Text.class,Text.class);
ControlledJob cjJob1 = new ControlledJob(job1.getConfiguration());
ControlledJob cjJob2 = new ControlledJob(job2.getConfiguration());
//创建管理job任务的control组
JobControl ssrs = new JobControl("ssrs");
//添加job
ssrs.addJob(cjJob1);
ssrs.addJob(cjJob2);
//添加任务依赖关系
cjJob2.addDependingJob(cjJob1);
//线程提交
Thread t1 = new Thread(ssrs);
t1.start();
while(!ssrs.allFinished()){
Thread.sleep(1000);
}
System.exit(0);
}
}
【Hadoop】MapReduce练习:多job关联实现倒排索引的更多相关文章
- Hadoop MapReduce编程 API入门系列之倒排索引(二十四)
不多说,直接上代码. 2016-12-12 21:54:04,509 INFO [org.apache.hadoop.metrics.jvm.JvmMetrics] - Initializing JV ...
- Hadoop MapReduce编程学习
一直在搞spark,也没时间弄hadoop,不过Hadoop基本的编程我觉得我还是要会吧,看到一篇不错的文章,不过应该应用于hadoop2.0以前,因为代码中有 conf.set("map ...
- Hadoop MapReduce编程入门案例
Hadoop入门例程简介 一个.有些指令 (1)Hadoop新与旧API差异 新API倾向于使用虚拟课堂(象类),而不是接口.由于这更easy扩展. 比如,能够无需改动类的实现而在虚类中加入一个方法( ...
- Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!
Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...
- 使用Python实现Hadoop MapReduce程序
转自:使用Python实现Hadoop MapReduce程序 英文原文:Writing an Hadoop MapReduce Program in Python 根据上面两篇文章,下面是我在自己的 ...
- MapReduce业务 - 图片关联计算
1.概述 最近在和人交流时谈到数据相似度和数据共性问题,而刚好在业务层面有类似的需求,今天和大家分享这类问题的解决思路,分享目录如下所示: 业务背景 编码实践 预览截图 下面开始今天的内容分享. 2. ...
- Hadoop Mapreduce 案例 wordcount+统计手机流量使用情况
mapreduce设计思想 概念:它是一个分布式并行计算的应用框架它提供相应简单的api模型,我们只需按照这些模型规则编写程序,即可实现"分布式并行计算"的功能. 案例一:word ...
- Hadoop学习笔记(8) ——实战 做个倒排索引
Hadoop学习笔记(8) ——实战 做个倒排索引 倒排索引是文档检索系统中最常用数据结构.根据单词反过来查在文档中出现的频率,而不是根据文档来,所以称倒排索引(Inverted Index).结构如 ...
- Hadoop MapReduce编程 API入门系列之计数器(二十七)
不多说,直接上代码. MapReduce 计数器是什么? 计数器是用来记录job的执行进度和状态的.它的作用可以理解为日志.我们可以在程序的某个位置插入计数器,记录数据或者进度的变化情况. Ma ...
随机推荐
- Android利用json进行网络解析
必须单开一个线程,android界面的主线程不会负责通信模块
- [MySQL优化] -- 如何使用SQL Profiler 性能分析器
mysql 的 sql 性能分析器主要用途是显示 sql 执行的整个过程中各项资源的使用情况.分析器可以更好的展示出不良 SQL 的性能问题所在. 下面我们举例介绍一下 MySQL SQL Profi ...
- 01-vue和api整合流程、CORS
1.后端代码 1.项目结构 2.项目代码 主url from django.contrib import admin from django.urls import path, include url ...
- 题解 [CF803C] Maximal GCD
题面 解析 一开始以为这题很难的... 其实只要设\(d\)为\(a\)的最大公因数, 即\(a[i]=s[i]*d\), 因为\(n=\sum_{i=1}^{n}a[i]=\sum_{i=1}^ns ...
- HDU 6058 - Kanade's sum | 2017 Multi-University Training Contest 3
/* HDU 6058 - Kanade's sum [ 思维,链表 ] | 2017 Multi-University Training Contest 3 题意: 给出排列 a[N],求所有区间的 ...
- Remove Mapping
http://social.msdn.microsoft.com/forums/vstudio/en-US/ffa3aa15-1d61-4464-ac4a-7a812d073a67/remove-ma ...
- php实现浏览器大文件分片上传
PHP用超级全局变量数组$_FILES来记录文件上传相关信息的. 1.file_uploads=on/off 是否允许通过http方式上传文件 2.max_execution_time=30 允许脚本 ...
- c++ const修饰词
常变量: const 类型说明符 变量名 // const int i = 20;常变量定义必需初始化赋值且变量值不可更改 常引用: const 类型说明符 &引用名 //引用:指 ...
- Pycharm下将py文件打包成exe文件
1. 在PyCharm下安装PyInstaller 1. 首先,打开自己要发布的工程 2. 点击底部的[Terminal]打开终端,中输入命令pip install pyinstaller后回车, ...
- js中的DOM对象和jQuery对象的比较
1. 二者的不同之处: 通过jQuery获取的元素是一个数组, 数组中包含着原生JS中的DOM对象. 例如, 针对下面的一个div结构: <div id="Box">& ...