mapreduce實現倒排索引

停不下的腳步發表於2015-01-27
目的:
產生一個資料集的索引以便提供更快的搜尋或資料豐富能力。

動機:
對大的資料集建立一個關鍵字的索引,通常可以方便通過指定關鍵字搜尋到其包含特定值的對應記錄。儘管建立倒排索引的過程需要預先進行額外的處理,但花費時間做預處理可以極大地縮減查詢時所需要的時間。

適用場景:
倒排索引通常用在需要快速搜尋查詢響應的場景。可以對一個查詢的結果進行預處理並存入資料庫中。

真實場景:
搜尋引擎通過建立索引來提高搜尋效能。
假設輸入一個關鍵字,讓搜尋引擎的爬蟲去抓取網上的資料並建立一個頁面的列表返回給你,這樣的查詢將花費非常長的時間才能完成。通過建立倒排索引,搜尋引擎可以預先知道關鍵字所對應的網頁,因此只要簡單地將相關內容展示給使用者就可以了。這樣的索引通常也會儲存在一個資料庫中來提高檢索的效率。建立一個倒排索引的工程對MapReduce來說非常簡單,因為MapReduce框架將負責處理大部分工作。
我們建立測試資料如下:
www.baidu.com zhangsan lisi wangwu renliu
www.google.com zhangsan lisi wangwu
www.sohu.com zhangsan lisi
www.163.com zhangsan

每行資料在模擬一個網頁,我們約定第一個field代表url,後面欄位代表該網頁中出現的關鍵字
通過倒排索引我們將得到如下結果:
zhangsan www.baidu.com www.google.com www.sohu.com www.163.com
lisi www.baidu.com www.google.com www.sohu.com
wangwu www.baidu.com www.google.com
renliu       www.baudu.com

我們可以看出,資料本來是以url作為索引、關鍵字為值的,經過倒排關鍵字稱為了索引、url為值。這樣就可以快速查到關鍵字對應的url。

package com.mr.invertedIndex;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;

/**
 * 倒排索引
 * 
 * @author luobao
 *
 */
public class inverteIndex {

	public static class MyMapper extends Mapper<Object, Text, Text, Text> {
		public void map(Object key, Text value, Context context)
				throws IOException, InterruptedException {
			String[] arrStr = value.toString().split(" ");
			for (int i = 1; i < arrStr.length; i++) {
				context.write(new Text(arrStr[i]), new Text(arrStr[0]));
			}
		}
	}

	public static class MyReducer extends Reducer<Text, Text, Text, Text> {
		public void reduce(Text key, Iterable<Text> values, Context context)
				throws IOException, InterruptedException {
			StringBuilder result = new StringBuilder();
			boolean first = true;
			for (Text val : values) {
				if (first) {
					result.append(val.toString());
					first = false;
				} else {
					result.append(" " + val.toString());
				}
			}
			context.write(key, new Text(result.toString()));
		}
	}

	public static void main(String[] args) throws Exception {
		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf);
		job.setJarByClass(inverteIndex.class);
		job.setMapperClass(MyMapper.class);
		job.setCombinerClass(MyReducer.class);
		job.setReducerClass(MyReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		FileInputFormat.addInputPath(job, new Path(
				"hdfs://192.168.40.186:9000/input/invertedIndex"));
		FileOutputFormat.setOutputPath(job, new Path(
				"hdfs://192.168.40.186:9000/output"));
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
}


相關文章