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. sqlserver数据库不能重命名报错5030

    在学习asp.net的时候使用mssql'经常会出现这种错误,数据库不能重名名5030的错误,其实很简单原因就是有应用程序正在占用这个连接,使用这样一行命令就可以查询出正在占用的连接 use mast ...

  2. vi/vim键盘对应图

    来源:http://www.runoob.com/linux/linux-vim.html

  3. JS获取地址栏的参数值

    function GetQueryString(name){ var reg = new RegExp("(^|&)"+ name +"=([^&]*)( ...

  4. java内嵌jetty服务器

    有的时候需要将一个简单的功能封装为服务,相比python使用flask.web.py的简洁,使用java-web显得太重量级,幸好,我们可以直接在java项目中使用jetty来搭建简易服务 1.pom ...

  5. Flink--sink到kafka

    package com.flink.DataStream import java.util.Properties import org.apache.flink.api.common.serializ ...

  6. zabbix邮箱报警设置&问题汇总

    zabbix邮件报警部署! Zabbix监控服务端.客户端都已经部署完成,被监控主机已经添加,Zabiix监控运行正常,通过查看Zabbix监控服务器,可以了解服务器的运行状态是否正常,运维人员不会时 ...

  7. Codeforces 311D Interval Cubing 数学 + 线段树 (看题解)

    Interval Cubing 这种数学题谁顶得住啊. 因为 (3 ^ 48) % (mod - 1)为 1 , 所以48个一个循环节, 用线段树直接维护. #include<bits/stdc ...

  8. appium---第一个脚本--启动一个已存在的app

    1.可以使用android-sdk中的aapt工具 ①.选择一个版本的build_tools,加入path环境变量中 ②.验证aapt环境是否正常 3.下载你要测试的包,放入某一地址中(随意):aap ...

  9. Ubuntu18.04上安装java

    安装java8 sudo add-apt-repository ppa:webupd8team/javasudo apt-get updatesudo apt-get install oracle-j ...

  10. POJ 2251 Dungeon Master (非三维bfs)

    Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 55224   Accepted: 20493 ...