倒序索引 简介
“倒排索引”是文档检索系统中最常用的数据结构,被广泛地应用于全文搜索引擎。它主要是用来存储某个单词(或词组)在一个文档或一组文档中的存储位置的映射,即提供了一种根据内容来查找文档的方式。由于不是根据文档来确定文档所包含的内容,而是进行相反的操作,因而称为倒排索引(Inverted Index)。
关于倒序索引更加详细的介绍MapReduce实现倒序索引
Hadoop 将数据传给 map 进行处理前会使用inputformat对数据进行处理:
1. 对数据进行切分,生成一组split分片,一个split分片会被分给一个mapper处理
2. 针对每个split,再创建一个RecordReaders读取split,并按照
package hadoop.invertedindex;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
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.GenericOptionsParser;
public class InvertedIndex {
public static class Map extends Mapper<LongWritable, Text, Text, Text>{
// word 用来储存单词和URI one 用来储存词频
private static Text word = new Text();
private static Text one = new Text();
protected void map(LongWritable key, Text value, Context context)
throws java.io.IOException ,InterruptedException {
// (FileSplit)context.getInputSplit() 获取<key, value> 对所属的FileSplit对象
// 在这里由于文件不大,每一个Split分片即是一个对应的文件
// 获取当前Split下的文件名称
String fileName = ((FileSplit)context.getInputSplit()).getPath().getName();
// StringTokenizer 是用来把字符串截取成一个个标记或单词的
StringTokenizer st = new StringTokenizer(value.toString());
while(st.hasMoreTokens()){
word.set(st.nextToken()+"\t"+fileName);
context.write(word, one);
}
};
}
/**
* Combine 的作用是完成词频统计
* @author Administrator
*
*/
public static class Combine extends Reducer<Text, Text, Text, Text>{
private static Text word = new Text();
private static Text index = new Text();
protected void reduce(Text key, Iterable<Text> values, Context context)
throws java.io.IOException ,InterruptedException {
// 对key进行操作, 截取分开 单词 和 URI
String[] splits = key.toString().split("\t");
if(splits.length != 2){
return ;
}
// 统计词频
long count = 0;
for (Text v : values) {
count++;
}
// 设置key 为 splits[0] 单词 value 为 splits[1] 文件名 + 次数
word.set(splits[0]);
index.set(splits[1]+":"+count);
context.write(word, index);
};
}
/**
* Reduce 的作用是生成文档列表
* @author Administrator
*
*/
public static class Reduce extends Reducer<Text, Text, Text, Text>{
private static StringBuilder sub = new StringBuilder(256);
private static Text index = new Text();
protected void reduce(Text word, Iterable<Text> values, Context context)
throws java.io.IOException ,InterruptedException {
for (Text v : values) {
sub.append(v.toString()).append(";");
}
index.set(sub.toString());
context.write(word, index);
sub.delete(0,sub.length());
};
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs();
if(otherArgs.length != 2){
System.err.println("Usage:InvertedIndex");
System.exit(2);
}
Job job = new Job(conf, "InvertedIndex");
job.setJarByClass(InvertedIndex.class);
//设置Map Combine Reduce 处理类
job.setMapperClass(Map.class);
job.setCombinerClass(Combine.class);
job.setReducerClass(Reduce.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
//设置输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
//设置输入和输出目录
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
在运行这个之前请确保Hadoop集群已经开启,并且保证eclipse能够正确的连接集群,不知道如何设置的可以看我之前发表的博客~~~
有问题可以留,回头去搞MapReduce对inner join的操作了