美文网首页BigData
MapReduce之倒排索引类应用

MapReduce之倒排索引类应用

作者: 跟着大数据和AI去旅行 | 来源:发表于2019-03-11 20:40 被阅读1次

应用需求

通常在数据文件中包含大量的单词,每个单词可能会出现多次,需要根据单词查找文档,这时就需要用到倒排索引。

应用场景

在全文检索系统或搜索引擎中,经常会用到根据单词查找文档。

解决方案

通常在 Map 过程中,对文档进行切分,把单词和文档URL设置为 Key,单词为文档中的次数为 Value,使用 Combine 函数对文档中的词频进行统计,然后将 单词作为 Key,文档URL和词频作为 Value 输出到 Reduce 中,Reduce 函数以单词为 Key,生成倒排索引。

倒排索引

倒排索引主要是用来存储某个单词(或词组)在一个文档或一组文档中的存储位置的映射,即提供一种根据内容来查找文档的方式。由于不是根据文档来确定文档所包含的内容,而是进行相反操作,因而成为倒排索引。

通常情况下,倒排索引由一个单词(或词组)以及相关的文档列表组成,文档列表中的文档或者是表示文档的ID号,或者是指文档所在位置的URL。在实际应用中文档通常带有权重,即记录单词在文档中出现的次数。如下面所示。
有下面三个文档:

D0.txt:
MapReduce is simple is easy
D1.txt:
MapReduce is powerful is userful
D2.txt:
Hello MapReduce Bye MapReduce

则 D0.txt、D1.txt和 D2.txt的倒排索引文件,如下所示:

Bye D2.txt:1;
Hello   D2.txt:1;
MapReduce   D2.txt:2;D1.txt:1;D0.txt:1;
easy    D0.txt:1;
is  D0.txt:2;D1.txt:2;
powerful    D1.txt:1;
simple  D0.txt:1;
userful D1.txt:1;

如上面倒排索引所示,倒排索引文件中的 MapReduce 一行表示:MapReduce 这个单词在文本D0中出现1次,D1中出现1次,D2中出现2次。
当搜索条件为 MapReduce、is、Simple时,对应的集合为:{D0,D1,D2} && {D0,D1} && {D0} = {D0},即文档 D0 包含了所要索引的单词,而且是连续的。

在实际的搜索引擎应用中,除了考虑词频外,还要考虑单词出现的位置,比如单词出现在标题和 URL 中就比出现在正文中的权重高。

分析与设计

Map过程

首先使用默认的TextInputFormat类对输入文件进行处理,得到文本中每行的偏移量及其内容,Map过程首先必须分析输入的<key, value>对,得到倒排索引中需要的三个信息:单词、文档URI和词频,如图所示:

bigdataInvertIndexMapper.jpg

存在两个问题,第一:<key, value>对只能有两个值,在不使用Hadoop自定义数据类型的情况下,需要根据情况将其中的两个值合并成一个值,作为value或key值;

第二,通过一个Reduce过程无法同时完成词频统计和生成文档列表,所以必须增加一个Combine过程完成词频统计.

这里将单词和文档URL组成 Key 值(如 MapReduce:D0.txt),将词频作为 Value,这样做的目的是可以将同一文档的相同单词的词频组成列表,传递给 Combine 过程,就可以计算同一文档中单词的词频。

package com.test.invertedindex;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;

public class InvertedIndexMapper extends Mapper<LongWritable, Text, Text, Text>{

    private Text keyInfo = new Text();  //存储单词和文档URL组合
    private Text valueInfo = new Text();    //存储词频
    private FileSplit fileSplit;    //存储 FileSplit对象,目的为获取文档URL
    
    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        //获取单词所属的 FileSplit 对象。
        fileSplit = (FileSplit) context.getInputSplit();
        
        String line = value.toString();
        StringTokenizer itr = new StringTokenizer(line);
        while(itr.hasMoreTokens()){
            //获取文件完整路径
            //keyInfo.set(itr.nextToken() + ":" + fileSplit.getPath().toString());
            //这里只获取文件的名称
            int splitIndex = fileSplit.getPath().toString().indexOf("D");
            //key值由单词和文档URL组成,如 "MapReduce:D0.txt"
            keyInfo.set(itr.nextToken() + ":" + fileSplit.getPath().toString().substring(splitIndex));
            
            //词频初始化为1
            valueInfo.set("1");
            
            context.write(keyInfo, valueInfo);
        }
    }

}

Combine 过程

经过 Map 方法处理后,Combine过程将key值相同的value值累加,得到一个单词在文档中的词频,如图。

bigdataInvertedIndexCombiner.jpg

如果直接将上图所示的输出作为Reduce过程的输入,在Shuffle过程将面临一个问题:所有具有相同单词的记录(由单词、文档URL和词频组成)应该交由同一个Reducer处理,但当前的Key值无法保证这一点,所以必须修改Key值和Value值。这次将单词作为Key值,文档URL和词频组成Value值(如 D0.txt:1).这样做的好处是可以利用MapReduce框架默认的HashPartitioner类完成Shuffle过程,将相同单词的所有记录发送给同一个Reducer进行处理。

package com.test.invertedindex;

import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

//计算每个单词所在文档的词频
public class InvertedIndexCombiner extends Reducer<Text, Text, Text, Text>{

    private Text info = new Text();
    
    @Override
    protected void reduce(Text key, Iterable<Text> values, Context context)
            throws IOException, InterruptedException {
        //统计词频
        int sum = 0;
        for (Text val : values) {
            sum += Integer.parseInt(val.toString());
        }
        
        int splitIndex = key.toString().indexOf(":");
        
        //重新设置 value 的值为文档URL和词频组成。
        info.set(key.toString().substring(splitIndex + 1) + ":" + sum);
        //重新设置 key 的值为单词
        key.set(key.toString().substring(0, splitIndex));
        
        
        context.write(key, info);
    }

}

Reduce 过程

经过上述两个过程后,Reduce过程只需将相同key值的value值组合成倒排索引文件所需的格式即可,剩下的事情就可以直接交给MapReduce框架进行处理。如图。

bigdataInvertedIndexReducer.jpg

更多精彩内容,欢迎关注微信公众号: 不会搬砖的码农

不会搬砖的码农

相关文章

  • MapReduce之倒排索引类应用

    应用需求 通常在数据文件中包含大量的单词,每个单词可能会出现多次,需要根据单词查找文档,这时就需要用到倒排索引。 ...

  • MapReduce 之倒排索引

    倒排索引 介绍: 即是 统计每篇文章 每个单词出现的次数,以此达到在搜索引擎中 搜索关键字,检索出出现关键字 最多...

  • MapReduce 案例之倒排索引

    1. 倒排索引 倒排索引是文档检索系统中最常用的数据结构,被广泛地应用于全文搜索引擎。 它主要是用来存储某个单词(...

  • MapReduce 案例之倒排索引

    1. 倒排索引 倒排索引是文档检索系统中最常用的数据结构,被广泛地应用于全文搜索引擎。 它主要是用来存储某个单词(...

  • Mapreduce案例之倒排索引

    1.数据准备 2.上传HDFS 3.执行Mapreduce分布式并行计算 3.1业务逻辑处理。 业务理解:通俗理解...

  • MapReduce 案例之倒排索引

    1. 倒排索引 倒排索引是文档检索系统中最常用的数据结构,被广泛地应用于全文搜索引擎。 它主要是用来存储某个单词(...

  • MapReduce基本原理及案例代码分享

    1. 背景知识 起源: Google最早用MapReduce做搜索引擎中的倒排索引,简单来说是: 统计每个词条与文...

  • Elasticsearch(一):概念与基本API

    安装 Elasticsearch 常用 API index Document 倒排索引与分词 倒排索引 倒排索引与...

  • 40、Python快速开发分布式搜索引擎Scrapy精讲—ela

    【百度云搜索,搜各种资料:http://www.81ad.cn】 倒排索引 倒排索引源于实际应用中需要根据属性的值...

  • MapReduce算法模式-倒排索引模式

    一、倒排索引 倒排索引,是一种为了提高搜索效率而创建的索引,是一种数据结构。在搜索索引中输入关键词,然后让搜索引擎...

网友评论

    本文标题:MapReduce之倒排索引类应用

    本文链接:https://www.haomeiwen.com/subject/lwftpqtx.html