【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 ...
随机推荐
- git log master..origin/master --oneline | wc -l 怎么知道本地仓库是不是最新的
git log master..origin/master --oneline | wc -l 怎么知道本地仓库是不是最新的 git fetch # 一定要先 fetch git log mast ...
- JavaScript中定义类的方式详解
本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的exte ...
- Android之Json
Servlet部分 public class JasonAction extends HttpServlet { private JsonService service; public void do ...
- CodeForces - 113B Petr# (后缀数组)
应该算是远古时期的一道题了吧,不过感觉挺经典的. 题意是给出三一个字符串s,a,b,求以a开头b结尾的本质不同的字符串数. 由于n不算大,用hash就可以搞,不过这道题是存在复杂度$O(nlogn)$ ...
- 【转】深入理解Spring的两大特征(IOC和AOP)
原文链接:https://blog.csdn.net/gloomy_114/article/details/68946881 众所周知,Spring的核心特性就是IOC和AOP,IOC(Inversi ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature
链接: https://codeforces.com/contest/1241/problem/C 题意: You are an environmental activist at heart but ...
- 题解 [51nod1274] 最长递增路径
题面 解析 这题一眼DP啊. 然而想了半天毫无思路. 后来看题解后发现可以按边权的大小顺序DP. 将边权从小到大排序,对于权值相同的边分为一组. 设\(f[i][0]\)表示经过当前权值的边后到达\( ...
- HFUUOJ1024 动态开点线段树+标记永久化
题意 分析 动态加点线段树,标记永久化好写常数小 Code #include<bits/stdc++.h> #define fi first #define se second #defi ...
- 修改checkbox样式-1
说明 使用伪类来对复选框进行样式修改.以下以最简单的一个样式修改为实例进行说明. 步骤介绍: 将一个label与复选框进行绑定,将两者放在同一个div下 调整 label的外部样式使其作为复选框的外形 ...
- IntelliJ IDEA 2017.3 搭建一个多模块的springboot项目(三)
你得先看完前两篇文章才可以进行第三章.这章我又新建了一个模块,起名叫project-core.建立方式与(一)里面一致,一个普通的maven模块.不需要勾选archetype的那种. 大家自己建好后, ...