概述

倒排索引(英语: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关联实现倒排索引的更多相关文章

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

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

  2. Hadoop MapReduce编程学习

    一直在搞spark,也没时间弄hadoop,不过Hadoop基本的编程我觉得我还是要会吧,看到一篇不错的文章,不过应该应用于hadoop2.0以前,因为代码中有  conf.set("map ...

  3. Hadoop MapReduce编程入门案例

    Hadoop入门例程简介 一个.有些指令 (1)Hadoop新与旧API差异 新API倾向于使用虚拟课堂(象类),而不是接口.由于这更easy扩展. 比如,能够无需改动类的实现而在虚类中加入一个方法( ...

  4. Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!

    Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...

  5. 使用Python实现Hadoop MapReduce程序

    转自:使用Python实现Hadoop MapReduce程序 英文原文:Writing an Hadoop MapReduce Program in Python 根据上面两篇文章,下面是我在自己的 ...

  6. MapReduce业务 - 图片关联计算

    1.概述 最近在和人交流时谈到数据相似度和数据共性问题,而刚好在业务层面有类似的需求,今天和大家分享这类问题的解决思路,分享目录如下所示: 业务背景 编码实践 预览截图 下面开始今天的内容分享. 2. ...

  7. Hadoop Mapreduce 案例 wordcount+统计手机流量使用情况

    mapreduce设计思想 概念:它是一个分布式并行计算的应用框架它提供相应简单的api模型,我们只需按照这些模型规则编写程序,即可实现"分布式并行计算"的功能. 案例一:word ...

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

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

  9. Hadoop MapReduce编程 API入门系列之计数器(二十七)

    不多说,直接上代码. MapReduce 计数器是什么?    计数器是用来记录job的执行进度和状态的.它的作用可以理解为日志.我们可以在程序的某个位置插入计数器,记录数据或者进度的变化情况. Ma ...

随机推荐

  1. hdu3715 Go Deeper[二分+2-SAT]/poj2723 Get Luffy Out[二分+2-SAT]

    这题转化一下题意就是给一堆形如$a_i + a_j \ne c\quad (a_i\in [0,1],c\in [0,2])$的限制,问从开头开始最多到哪条限制全是有解的. 那么,首先有可二分性,所以 ...

  2. localstorage ie11不支持

    据我所知,localstorage在高版本的ie.谷歌.火狐下都是支持的,以前没在ie上看过,不清楚,今天我用ie11打开我vue编译后的html,竟然发现不支持localstorage了,用仿真的i ...

  3. CF311B Cats Transport(斜率优化)

    题目描述 Zxr960115 是一个大农场主.他养了m只可爱的猫子,雇佣了p个铲屎官.这里有一条又直又长的道路穿过了农场,有n个山丘坐落在道路周围,编号自左往右从1到n.山丘i与山丘i-1的距离是Di ...

  4. Codeforces Round #509 (Div. 2) E. Tree Reconstruction(构造)

    题目链接:http://codeforces.com/contest/1041/problem/E 题意:给出n - 1对pair,构造一颗树,使得断开其中一条边,树两边的最大值为 a 和 b . 题 ...

  5. C# WebBrowser使用 网络(二)

    WebBrowser 简单操作 Form 代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); ...

  6. 智能指针unique_ptr记录

    unique_ptr 对对象独有管理,无法复制,共享,值传递,可以使用move语义来转移控制权. std::default_delete<int> d; std::unique_ptr&l ...

  7. bbs-admin

    目录 引入单例----单例补充 admin---url/注册的自定义配置 解析admin源码 django-admin注册账号-----创建超级用户 python manage.py createsu ...

  8. windows下mysql 主库从库同步

    今天先讲讲数据库的主从同步,两个好处: 一是读写分离可以用上.比如 写操作就写到主数据库,读就再从库读取 二是纯粹给数据库备份,以防硬盘彻底崩了 主从数据库操作准备: 两台电脑,都安装好mysql 5 ...

  9. 修改tomcat控制台的标题

    Tomcat的bin目录下,创建一个名为setenv.bat的文件. setenv.bat  编辑内容 : set TITLE = 想要命名的标题名称  保存修改.重新启动. 第二种. 修改tomca ...

  10. linux磁盘内存满了?删除大文件依然不起作用

    好久没有更新博客了,但并不代表自己没有遇到技术问题了.遇到了一大堆,也解决了一大堆.只是没有记下来的欲望了,似乎大脑就这样,忘不掉.啥都忘不掉了,即使忘掉了也知道如何百度了. 查看目录大小命令 du命 ...