mapreduce实现搜索引擎简单的倒排索引
使用hadoop版本为2.2.0
倒排索引简单的可以理解为全文检索某个词
例如:在a.txt 和b.txt两篇文章分别中查找统计hello这个单词出现的次数,出现次数越多,和关键词的吻合度就越高
现有a.txt内容如下:
hello tom
hello jerry
hello kitty
hello world
hello tom
b.txt内容如下:
hello jerry
hello tom
hello world
在hadoop平台上编写mr代码分析统计各个单词在两个文本中出现的次数
其实也只是WordCount程序的改版而已~
将两个文本上传到hdfs根目录的ii文件夹下(mr直接读取ii文件夹,会读取所有没有以_(下划线)开头的文件)
编写mr代码
首先分析,map输入的格式为
该行偏移量 该行文本
如:
0 hello
我们知道,map的输出之后会根据相同的key来进行合并
而每个单词都不是唯一的,它可能在两个文本中都出现,使用单词作为key的话无法分辨出该单词属于哪个文本
而使用文本名字作为key的话,那么将达到我们原来的目的,因为map的输出就会变成a.txt->单词..单词..单词
这显然不是我们想要的结果
所以map输出的格式应该为
单个单词->所在文本 1
如:
hello->a.txt 1
这里用->作为单词和所在文本的分隔
这样就可以在根据key进行合并的时候不会影响到我们的结果
map代码如下:
public static class MyMapper extends Mapper<LongWritable, Text, Text, Text> {
private Text k = new Text();
private Text v = new Text();
protected void map(
LongWritable key,
Text value,
org.apache.hadoop.mapreduce.Mapper<LongWritable, Text, Text, Text>.Context context)
throws java.io.IOException, InterruptedException {
String[] data = value.toString().split(" ");
//FileSplit类从context上下文中得到,可以获得当前读取的文件的路径
FileSplit fileSplit = (FileSplit) context.getInputSplit();
//文件路径为hdfs://hadoop:9000/ii/a.txt
//根据/分割取最后一块即可得到当前的文件名
String[] fileNames = fileSplit.getPath().toString().split("/");
String fileName = fileNames[fileNames.length - 1];
for (String d : data) {
k.set(d + "->" + fileName);
v.set("1");
context.write(k, v);
}
};
}
在map执行完毕之后
我们需要一个combiner来帮助完成一些工作
注意,combiner的输入格式和输出格式是一致的,也就是map的输出格式,否则会出错
再次分析,根据key合并value之后的键值对是这个样子的:
(hello->a.txt,{1,1,1,1,1})
combiner要做的工作就是讲values统计累加
并将key的单词和文本分隔开,将文本名和统计之后的values组合在一起形成新的value
如:
(hello,a.txt->5)
为什么要这么做?
因为在combiner执行完毕之后
还会根据key进行一次value的合并,跟map之后的是一样的
将key相同的value组成一个values集合
如此一来,在经过combiner执行之后,到达reduce的输入就变成了
(hello,{a.txt->5,b.txt->3})
这样的格式,然后在reduce中循环将values输出不就是我们想要的结果了吗~
combiner代码如下:
public static class MyCombiner extends Reducer<Text, Text, Text, Text> {
private Text k = new Text();
private Text v = new Text();
protected void reduce(
Text key,
java.lang.Iterable<Text> values,
org.apache.hadoop.mapreduce.Reducer<Text, Text, Text, Text>.Context context)
throws java.io.IOException, InterruptedException {
//分割文件名和单词
String[] wordAndPath = key.toString().split("->");
//统计出现次数
int counts = 0;
for (Text t : values) {
counts += Integer.parseInt(t.toString());
}
//组成新的key-value输出
k.set(wordAndPath[0]);
v.set(wordAndPath[1] + "->" + counts);
context.write(k, v);
};
}
接下来reduce的工作就简单了
代码如下:
public static class MyReducer extends Reducer<Text, Text, Text, Text> {
private Text v = new Text();
protected void reduce(
Text key,
java.lang.Iterable<Text> values,
org.apache.hadoop.mapreduce.Reducer<Text, Text, Text, Text>.Context context)
throws java.io.IOException, InterruptedException {
String res = "";
for (Text text : values) {
res += text.toString() + "\r";
}
v.set(res);
context.write(key, v);
};
}
main方法代码:
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path inPath = new Path("hdfs://hadoop:9000" + args[0]);
Path outPath = new Path("hdfs://hadoop:9000" + args[1]);
if (fs.exists(outPath)) {
fs.delete(outPath, true);
}
Job job = Job.getInstance(conf);
job.setJarByClass(InverseIndex.class);
FileInputFormat.setInputPaths(job, inPath);
job.setInputFormatClass(TextInputFormat.class);
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setCombinerClass(MyCombiner.class);
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileOutputFormat.setOutputPath(job, outPath);
job.setOutputFormatClass(TextOutputFormat.class);
job.waitForCompletion(true);
}
在hadoop上运行jar包执行结果如图:
初学hadoop,仅作笔记之用,其中如有错误望请告知^-^
mapreduce实现搜索引擎简单的倒排索引的更多相关文章
- [Search Engine] 搜索引擎技术之倒排索引
倒排索引是搜索引擎中最为核心的一项技术之一,可以说是搜索引擎的基石.可以说正是有了倒排索引技术,搜索引擎才能有效率的进行数据库查找.删除等操作. 1. 倒排索引的思想 倒排索引源于实际应用中需要根据属 ...
- ES搜索引擎-简单入门
基本概念: 索引Index es吧数据放到一个或者多个索引中,如果用关系型数据库模型对比,索引的地位与数据库实例(db)相当.索引存放和读取的基本单元是文档(document).es内部使用的是apa ...
- 国内最全最详细的hadoop2.2.0集群的MapReduce的最简单配置
简介 hadoop2的中的MapReduce不再是hadoop1中的结构已经没有了JobTracker,而是分解成ResourceManager和ApplicationMaster.这次大变革被称为M ...
- mapreduce on yarn简单内存分配解释
关于mapreduce程序运行在yarn上时内存的分配一直是一个让我蒙圈的事情,单独查任何一个资料都不能很好的理解透彻.于是,最近查了大量的资料,综合各种解释,终于理解到了一个比较清晰的程度,在这里将 ...
- [How to] MapReduce on HBase ----- 简单二级索引的实现
1.简介 MapReduce计算框架是二代hadoop的YARN一部分,能够提供大数据量的平行批处理.MR只提供了基本的计算方法,之所以能够使用在不用的数据格式上包括HBase表上是因为特定格式上的数 ...
- Hadoop(11)-MapReduce概述和简单实操
1.MapReduce的定义 2.MapReduce的优缺点 优点 缺点 3.MapReduce的核心思想 4.MapReduce进程 5.常用数据序列化类型 6.MapReduce的编程规范 用户编 ...
- MapReduce原理及简单实现
MapReduce是Google在2004年发表的论文<MapReduce: Simplified Data Processing on Large Clusters>中提出的一个用于分布 ...
- MapReduce应用案例--简单排序
1. 设计思路 在MapReduce过程中自带有排序,可以使用这个默认的排序达到我们的目的. MapReduce 是按照key值进行排序的,我们在Map过程中将读入的数据转化成IntWritable类 ...
- MapReduce应用案例--简单的数据去重
1. 设计思路 去重,重点就是无论某个数据在文件中出现多少次,最后只是输出一次就可以. 根据这一点,我们联想到在reduce阶段数据输入形式是 <key, value list>,只要是k ...
随机推荐
- RabbitMQ消息队列(四): 消息路由
1. 路由: 前面的示例中,我们或得到的消息为广播消息,但是无法更精确的获取消息的子集,比如:日志消息,worker1只需要error级别的日志, 而worker2需要info,warning,err ...
- rest-framework-@action()装饰器
路由Routers 使用方法: 在urls.py中定义路由 from rest_framework.routers import DefaultRouter # 定义视图集的路由 router = ...
- 【SQL】约束与触发器2
3.修改约束 3.1给约束命名 按如下格式命名: name ) CONSTRAINT NameIsKey PRIMARY KEY gender ) CONSTRAINT NoAndro CHECK ( ...
- KVM(二)CPU 和内存虚拟化
1. 为什么需要 CPU 虚拟化 X86 操作系统是设计在直接运行在裸硬件设备上的,因此它们自动认为它们完全占有计算机硬件.x86 架构提供四个特权级别给操作系统和应用程序来访问硬件. Ring 是指 ...
- SQLAlchemy技术文档(中文版)-上
转自:http://www.cnblogs.com/iwangzc/p/4112078.html 1.版本检查 import sqlalchemy sqlalchemy.__version__ 2.连 ...
- head first (二):观察者模式
首先推荐一下别人写的,很不错可以参考,http://www.cnblogs.com/li-peng/archive/2013/02/04/2892116.html 1.定义 观察者模式:在对象之间定义 ...
- centos6.5 中文输入法图标和提示都不见了【解决】
原因python升级引起的 两步解决: # vi /usr/bin/ibus-setup # vi /usr/libexec/ibus-ui-gtk 把这两个文件中的exec python 修改为 e ...
- SecureCRT的安装、介绍、简单操作
网上看到一篇名为<SecureCRT的使用方法和技巧(详细使用教程)>的secureCRT教程,可能软件版本与我不一样我安装的是8.1. 原文来源:http://www.jb51.net/ ...
- Python_Tips[7] -> 偏函数
偏函数 / Partial Function 使用偏函数可以对函数的部分预先知道的参数进行冻结,从而缓存函数参数,而在运行时再释放参数进行使用.所以偏函数适用于需要多次调用同样一个函数且其中一个参数固 ...
- 高效mysql的习惯(程序员版本)
高效的mysql 一定要有主键 如果没有主键: 数据多次读写后可能更离散,有更多随机I/O MySQL复制环境中,如果选择RBR模式,没有主键的update需要读全表,导致复制延迟 好的主键特点: 没 ...