搜尋引擎:MapReduce實戰----倒排索引
1.倒排索引簡介
倒排索引(Inverted index),也常被稱為反向索引、置入檔案或反向檔案,是一種索引方法,被用來儲存在全文搜尋下某個單詞在一個文件或者一組文件中的儲存位置的對映。它是文件檢索系統中最常用的資料結構。
有兩種不同的反向索引形式:
- 一條記錄的水平反向索引(或者反向檔案索引)包含每個引用單詞的文件的列表。
- 一個單詞的水平反向索引(或者完全反向索引)又包含每個單詞在一個文件中的位置。
後者的形式提供了更多的相容性(比如短語搜尋),但是需要更多的時間和空間來建立。
舉例:
以英文為例,下面是要被索引的文字:
T0 = "it is what it is"
T1 = "what is it"
T2 = "it is a banana"
我們就能得到下面的反向檔案索引:
1
2
3
4
5
|
"a": {2} "banana": {2} "is": {0, 1, 2} "it": {0, 1, 2} "what": {0, 1} |
檢索的條件"what"
, "is"
和 "it"
將對應這個集合:{0,1}∩{0,1,2}∩{0,1,2}={0,1}。
對相同的文字,我們得到後面這些完全反向索引,有文件數量和當前查詢的單詞結果組成的的成對資料。 同樣,文件數量和當前查詢的單詞結果都從零開始。
所以,"banana": {(2, 3)}
就是說 “banana”在第三個文件裡 (T2),而且在第三個文件的位置是第四個單詞(地址為 3)。
1
2
3
4
5
|
"a": {(2, 2)} "banana": {(2, 3)} "is": {(0, 1), (0, 4), (1, 1), (2, 1)} "it": {(0, 0), (0, 3), (1, 2), (2, 0)} "what": {(0, 2), (1, 0)} |
如果我們執行短語搜尋"what is it"
我們得到這個短語的全部單詞各自的結果所在文件為文件0和文件1。但是這個短語檢索的連續的條件僅僅在文件1得到。
2.分析和設計
(1)Map過程
首先使用預設的TextInputFormat類對輸入檔案進行處理,得到文字中每行的偏移量及其內容,Map過程首先必須分析輸入的<key, value>對,得到倒排索引中需要的三個資訊:單詞、文件URI和詞頻,如圖所示:
存在兩個問題,第一:<key, value>對只能有兩個值,在不使用Hadoop自定義資料型別的情況下,需要根據情況將其中的兩個值合併成一個值,作為value或key值;
第二,通過一個Reduce過程無法同時完成詞頻統計和生成文件列表,所以必須增加一個Combine過程完成詞頻統計
public static class Map extends Mapper<Object,Text,Text,Text>{ private Text keyInfo = new Text(); private Text valueInfo = new Text(); private FileSplit split; //儲存所在檔案的路徑 public void map(Object key,Text value,Context context) throws IOException, InterruptedException{ split = (FileSplit)context.getInputSplit(); //獲取當前任務分割的單詞所在的檔案路徑 StringTokenizer itr = new StringTokenizer(value.toString()); while(itr.hasMoreTokens()){ keyInfo.set(itr.nextToken()+"+"+split.getPath().toString()); //keyvalue是由單詞和URI組成的 valueInfo.set("1"); //value值設定成1 context.write(keyInfo,valueInfo); } } } |
(2)Combine過程
將key值相同的value值累加,得到一個單詞在文件中的詞頻,如圖
public static class Combiner extends Reducer<Text,Text,Text,Text>{ private Text info = new Text(); public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{ int sum = 0; for(Text value:values){ sum += Integer.parseInt(value.toString()); } // int index = key.toString().indexOf("+"); // info.set(key.toString().substring(index+1)+":"+sum); // key.set(key.toString().substring(0,index)); String record = key.toString(); String[] str = record.split("[+]"); info.set(str[1]+":"+sum); key.set(str[0]); context.write(key,info); } } |
(3)Reduce過程
講過上述兩個過程後,Reduce過程只需將相同key值的value值組合成倒排索引檔案所需的格式即可,剩下的事情就可以直接交給MapReduce框架進行處理了
public static class Reduce extends Reducer<Text,Text,Text,Text>{ private Text result = new Text(); public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{ String value =new String(); for(Text value1:values){ value += value1.toString()+" ; "; } result.set(value); context.write(key,result); } } |
完整程式碼如下:
package ReverseIndex; import java.io.*; import java.util.StringTokenizer; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.*; 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; public class ReverseIndex { public static class Map extends Mapper<Object,Text,Text,Text>{ private Text keyInfo = new Text(); private Text valueInfo = new Text(); private FileSplit split; //儲存所在檔案的路徑 public void map(Object key,Text value,Context context) throws IOException, InterruptedException{ split = (FileSplit)context.getInputSplit(); //獲取當前任務分割的單詞所在的檔案路徑 StringTokenizer itr = new StringTokenizer(value.toString()); while(itr.hasMoreTokens()){ keyInfo.set(itr.nextToken()+"+"+split.getPath().toString()); //keyvalue是由單詞和URI組成的 valueInfo.set("1"); //value值設定成1 context.write(keyInfo,valueInfo); } } } public static class Combiner extends Reducer<Text,Text,Text,Text>{ private Text info = new Text(); public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{ int sum = 0; for(Text value:values){ sum += Integer.parseInt(value.toString()); } //下面三行註釋和緊接著四行功能一樣,只不過實現方法不一樣罷了 // info.set(key.toString().substring(index+1)+":"+sum); // key.set(key.toString().substring(0,index)); //對傳進來的key進行拆分,以+為界 String[] str = record.split("[+]"); info.set(str[1]+":"+sum); key.set(str[0]); context.write(key,info); } } public static class Reduce extends Reducer<Text,Text,Text,Text>{ private Text result = new Text(); public void reduce(Text key,Iterable<Text>values,Context context) throws IOException, InterruptedException{ String value =new String(); for(Text value1:values){ value += value1.toString()+" ; "; } result.set(value); context.write(key,result); } } public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { // TODO Auto-generated method stub Job job = new Job(); job.setJarByClass(ReverseIndex.class); job.setNumReduceTasks(1); //設定reduce的任務數量為1,平常的小測試不需要開闢太多的reduce任務程式 job.setMapperClass(Map.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(Text.class); job.setCombinerClass(Combiner.class); job.setReducerClass(Reduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); FileInputFormat.addInputPath(job, new Path("/thinkgamer/input")); FileOutputFormat.setOutputPath(job, new Path("/thinkgamer/output")); System.exit(job.waitForCompletion(true) ? 0 : 1); } } |
相關文章
- MapReduce實戰:倒排索引索引
- mapreduce實現倒排索引索引
- 【預研】搜尋引擎基礎——inverted index(倒排索引)Index索引
- 後端技術雜談1:搜尋引擎基礎倒排索引後端索引
- MapReduce實現倒排索引(簡單思路)索引
- 細節決定成敗 MapReduce任務實戰 倒排索引索引
- 用 Golang 寫一個搜尋引擎(0x02)--- 倒排索引技術Golang索引
- 搜尋引擎核心技術與演算法 —— 詞項詞典與倒排索引優化演算法索引優化
- 搜尋引擎核心技術與演算法 —— 詞項詞典與倒排索引最佳化演算法索引
- 搜尋學習基礎--倒排索引的過程解讀索引
- MapReduce程式設計例項之倒排索引 1程式設計索引
- 基於 Elasticsearch 的站內搜尋引擎實戰Elasticsearch
- ELKStack及Solr企業級搜尋引擎實戰Solr
- 搜尋引擎-03-搜尋引擎原理
- 直播開發app,實時搜尋、搜尋引擎框APP
- Elasticsearch線上搜尋引擎讀寫核心原理深度認知-搜尋系統線上實戰Elasticsearch
- 海量資料搜尋---搜尋引擎
- 搜尋引擎必看的入門書籍——《搜尋引擎:資訊檢索實踐》
- 48_初識搜尋引擎_快速上機動手實戰Query DSL搜尋語法
- 搜尋引擎索引資料結構和演算法索引資料結構演算法
- 50_初識搜尋引擎_上機動手實戰常用的各種query搜尋語法
- 51_初識搜尋引擎_上機動手實戰多搜尋條件組合查詢
- 搜尋引擎es-分詞與搜尋分詞
- ElasticSearch 倒排索引(Inverted Index)| 什麼是倒排索引?Elasticsearch索引Index
- 搜尋引擎索引的資料結構和演算法索引資料結構演算法
- ElasticSearch全文搜尋引擎Elasticsearch
- 搜尋引擎語法
- 搜尋引擎命令大全
- 搜尋引擎程式碼
- 搜尋引擎面試題面試題
- TableStore實戰:GEO索引打造億量級店鋪搜尋系統索引
- 52_初識搜尋引擎_上機動手實戰如何定位不合法的搜尋以及其原因
- 用 Golang 寫一個搜尋引擎(0x07)--- 正排索引Golang索引
- MapReduce 實現 搜尋指數統計和找到人氣王
- 搜尋引擎分散式系統思考實踐分散式
- 自己動手實現主題搜尋引擎
- 搜尋引擎優化(SEO)優化
- 搜尋引擎框架介紹框架