日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hadoop入门(十八)Mapreduce的倒排索引程序

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hadoop入门(十八)Mapreduce的倒排索引程序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、簡介

"倒排索引"是文檔檢索系統中最常用的數據結構,被廣泛地應用于全文搜索引擎。它主要是用來存儲某個單詞(或詞組)在一個文檔或一組文檔中的存儲位置的映射,即提供了一種根據內容來查找文檔的方式。由于不是根據文檔來確定文檔所包含的內容,而是進行相反的操作,因而稱為倒排索引(Inverted Index)。

?

二、例子

(1)實例描述
通常情況下,倒排索引由一個單詞(或詞組)以及相關的文檔列表組成,文檔列表中的文檔或者是標識文檔的ID號,或者是指文檔所在位置的URL
在實際應用中,還需要給每個文檔添加一個權值,用來指出每個文檔與搜索內容的相關度

樣例輸入: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
1)file1: ?
MapReduce is simple
2)file2: ?
MapReduce is powerful is simple?
3)file3: ?
Hello MapReduce bye MapReduce
?期望輸出:

MapReduce??????file1.txt:1;file2.txt:1;file3.txt:2;
is????????    file1.txt:1;file2.txt:2;
simple???????? ??file1.txt:1;file2.txt:1;
powerful???  ?file2.txt:1;
Hello???????  ?file3.txt:1;
bye???????  ???file3.txt:1;

(2)問題分析
實現"倒排索引"只要關注的信息為:單詞、文檔URL及詞頻。但是在實現過程中,索引文件的格式會略有所不同,以避免重寫OutPutFormat類

(3)實現步驟

1)Map過程?
????首先使用默認的TextInputFormat類對輸入文件進行處理,得到文本中每行的偏移量及其內容。顯然,Map過程首先必須分析輸入的<key,value>對,得到倒排索引中需要的三個信息:單詞、文檔URL和詞頻

存在兩個問題:
第一,<key,value>對只能有兩個值,在不使用Hadoop自定義數據類型的情況下,需要根據情況將其中兩個值合并成一個值,作為key或value值;
第二,通過一個Reduce過程無法同時完成詞頻統計和生成文檔列表,所以必須增加一個Combine過程完成詞頻統計。?

單詞和URL組成key值(如"MapReduce:file1.txt"),將詞頻作為value,這樣做的好處是可以利用MapReduce框架自帶的Map端排序,將同一文檔的相同單詞的詞頻組成列表,傳遞給Combine過程,實現類似于WordCount的功能。

2)Combine過程?
????經過map方法處理后,Combine過程將key值相同的value值累加,得到一個單詞在文檔在文檔中的詞頻,如果直接將圖所示的輸出作為Reduce過程的輸入,在Shuffle過程時將面臨一個問題:所有具有相同單詞的記錄(由單詞、URL和詞頻組成)應該交由同一個Reducer處理,但當前的key值無法保證這一點,所以必須修改key值和value值。
這次將單詞作為key值,URL和詞頻組成value值(如"file1.txt:1")。可以利用MapReduce框架默認的HashPartitioner類完成Shuffle過程,將相同單詞的所有記錄發送給同一個Reducer進行處理

3)Reduce過程?
經過上述兩個過程后,Reduce過程只需將相同key值的value值組合成倒排索引文件所需的格式即可,剩下的事情就可以直接交給MapReduce框架進行處理了

4)需要解決的問題
本倒排索引在文件數目上沒有限制,但是單詞文件不宜過大(具體值與默認HDFS塊大小及相關配置有關),要保證每個文件對應一個split。否則,由于Reduce過程沒有進一步統計詞頻,最終結果可能會出現詞頻未統計完全的單詞。可以通過重寫InputFormat類將每個文件為一個split,避免上述情況。或者執行兩次MapReduce,第一次MapReduce用于統計詞頻,第二次MapReduce用于生成倒排索引。除此之外,還可以利用復合鍵值對等實現包含更多信息的倒排索引。

(4)關鍵代碼

package com.mk.mapreduce;import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.io.WritableComparable; 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.jute.Index;import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.net.URI; import java.util.*; import java.util.stream.Collectors;public class InvertedIndex {public static class InvertedIndexMapper extends Mapper<LongWritable, Text, Text, Text> {private final Text newKey = new Text();private final Text newValue = new Text("1");@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {if (StringUtils.isBlank(value.toString())) {System.out.println("空白行");return;}StringTokenizer tokenizer = new StringTokenizer(value.toString());FileSplit fileInputSplit = (FileSplit) context.getInputSplit();String fileName = fileInputSplit.getPath().getName();while (tokenizer.hasMoreTokens()) {String word = tokenizer.nextToken();newKey.set(word + "\u0001" + fileName);context.write(newKey, newValue);}}}public static class InvertedIndexCombiner extends Reducer<Text, Text, Text, Text> {private final Text newKey = new Text();private final Text newValue = new Text();@Overrideprotected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {String[] keys = key.toString().split("\u0001");List<String> list = new LinkedList<>();values.forEach(v -> list.add(v.toString()));int count = list.stream().map(Integer::valueOf).reduce(0, (s, a) -> s + a);newKey.set(keys[0]);newValue.set(keys[1] + "\u0001" + count);context.write(newKey, newValue);}}public static class InvertedIndexReducer extends Reducer<Text, Text, Text, Text> {private final Text newValue = new Text();@Overrideprotected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {Map<String, Integer> map = new HashMap<>();for (Text v : values) {String[] value = v.toString().split("\u0001");Integer count = map.get(value[0]);if (Objects.isNull(count)) {count = Integer.parseInt(value[1]);} else {count = count + Integer.parseInt(value[1]);}map.put(value[0], count);}String info = map.entrySet().stream().sorted((a, b) -> {int c = a.getValue() - b.getValue();if (c != 0)return c;return a.getKey().compareTo(b.getKey());}).reduce(new StringBuilder(), (StringBuilder s, Map.Entry<String, Integer> v) -> {s.append(v.getKey()).append(" ").append(v.getValue()).append(";");return s;}, StringBuilder::append).toString();newValue.set(info);context.write(key, newValue);}}public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {String uri = "hdfs://192.168.150.128:9000";String input = "/invertedIndex/input";String output = "/invertedIndex/output";Configuration conf = new Configuration();if (System.getProperty("os.name").toLowerCase().contains("win"))conf.set("mapreduce.app-submission.cross-platform", "true");FileSystem fileSystem = FileSystem.get(URI.create(uri), conf);Path path = new Path(output);fileSystem.delete(path, true);Job job = new Job(conf, "InvertedIndex");job.setJar("./out/artifacts/hadoop_test_jar/hadoop-test.jar");job.setJarByClass(InvertedIndex.class);job.setMapperClass(InvertedIndexMapper.class);job.setCombinerClass(InvertedIndexCombiner.class);job.setReducerClass(InvertedIndexReducer.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(Text.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(Text.class);FileInputFormat.addInputPaths(job, uri + input);FileOutputFormat.setOutputPath(job, new Path(uri + output));boolean ret = job.waitForCompletion(true);System.out.println(job.getJobName() + "-----" + ret);} }

?

?

?

總結

以上是生活随笔為你收集整理的Hadoop入门(十八)Mapreduce的倒排索引程序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。