使用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实现搜索引擎简单的倒排索引的更多相关文章

  1. [Search Engine] 搜索引擎技术之倒排索引

    倒排索引是搜索引擎中最为核心的一项技术之一,可以说是搜索引擎的基石.可以说正是有了倒排索引技术,搜索引擎才能有效率的进行数据库查找.删除等操作. 1. 倒排索引的思想 倒排索引源于实际应用中需要根据属 ...

  2. ES搜索引擎-简单入门

    基本概念: 索引Index es吧数据放到一个或者多个索引中,如果用关系型数据库模型对比,索引的地位与数据库实例(db)相当.索引存放和读取的基本单元是文档(document).es内部使用的是apa ...

  3. 国内最全最详细的hadoop2.2.0集群的MapReduce的最简单配置

    简介 hadoop2的中的MapReduce不再是hadoop1中的结构已经没有了JobTracker,而是分解成ResourceManager和ApplicationMaster.这次大变革被称为M ...

  4. mapreduce on yarn简单内存分配解释

    关于mapreduce程序运行在yarn上时内存的分配一直是一个让我蒙圈的事情,单独查任何一个资料都不能很好的理解透彻.于是,最近查了大量的资料,综合各种解释,终于理解到了一个比较清晰的程度,在这里将 ...

  5. [How to] MapReduce on HBase ----- 简单二级索引的实现

    1.简介 MapReduce计算框架是二代hadoop的YARN一部分,能够提供大数据量的平行批处理.MR只提供了基本的计算方法,之所以能够使用在不用的数据格式上包括HBase表上是因为特定格式上的数 ...

  6. Hadoop(11)-MapReduce概述和简单实操

    1.MapReduce的定义 2.MapReduce的优缺点 优点 缺点 3.MapReduce的核心思想 4.MapReduce进程 5.常用数据序列化类型 6.MapReduce的编程规范 用户编 ...

  7. MapReduce原理及简单实现

    MapReduce是Google在2004年发表的论文<MapReduce: Simplified Data Processing on Large Clusters>中提出的一个用于分布 ...

  8. MapReduce应用案例--简单排序

    1. 设计思路 在MapReduce过程中自带有排序,可以使用这个默认的排序达到我们的目的. MapReduce 是按照key值进行排序的,我们在Map过程中将读入的数据转化成IntWritable类 ...

  9. MapReduce应用案例--简单的数据去重

    1. 设计思路 去重,重点就是无论某个数据在文件中出现多少次,最后只是输出一次就可以. 根据这一点,我们联想到在reduce阶段数据输入形式是 <key, value list>,只要是k ...

随机推荐

  1. 僵尸进程(zombie process)

    僵尸进程(zombie process) http://blog.csdn.net/crfoxzl/article/details/2124718 杀死Linux中的defunct进程(僵尸进程)的方 ...

  2. wait(),sleep(),notify(),join()

    wait()注意以下几点: 1)wait()是属于Object类的方法. 2)调用了wait()之后会引起当前线程处于等待状态. 3)将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停 ...

  3. 动态加载ajax 腾讯视频评论

    import urllib import urllib2 import os import requests import re import json sns_url = 'http://sns.v ...

  4. python笔记-邮件发送(smtplib)【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/python/ 前言 本篇总结了QQ邮箱和163邮箱发送邮件,邮件包含html中文和附件 ...

  5. MyBatis入门实例 ——Mapper.xml(zz)

    <?xml version="1.0" encoding="UTF-8" ?>    <!DOCTYPE mapper        PUBL ...

  6. 怎么将string list 转成有特殊字符分开字符串

    https://stackoverflow.com/questions/4021851/join-string-list-elements-with-a-delimiter-in-one-step Y ...

  7. (二)shell变量

    (1)自定义变量 定义变量 变量名=变量值 变量名必须以字母或下划线开头,不能数字开头,区分大小写,ip=114.114.114.114 引用变量: $变量名 ${变量名} 查看变量: echo $变 ...

  8. (一)shell基础

    (1)shell作用: 1)自动化批量系统初始化程序(软件安装,时区设置,安全策略) 2)自动化批量软件部署程序(LNMP,LAMP,LNTM) 3)管理应用程序(kvm,集群管理扩容) 4)日志分析 ...

  9. ubuntu下配置ProFtpd服务使用sqlite3作为后端用户认证

    个人机器需要开个文件共享,Linux机器懒得配置SMB,就直接安装了ProFtpd,以做FTP服务器 Ubuntu安装挺简单,可使用就不那么友好了,配合GAdmin-Proftpd,一样不好用. 首先 ...

  10. golang笔记:cookie

    在同一个问题上栽了两次,以后碰到cookie出问题多半都是因为这个. Request.Cookie(name)取Cookie的时候,返回值只有name和value cookie.go cookies ...