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

夜深了我还没有休息,临近过春节了,可是加班还是那么的多,心累了,好想找个地方休息休息,放松下自己 、、、
可是路还要走,生活还要继续,洗把脸,我还要战斗,生活就那点事、、、

一、倒排索引

倒排索引,是一种为了提高搜索效率而创建的索引,是一种数据结构。在搜索索引中输入关键词,然后让搜索引擎取互联网采集包括关键词的信息网络列表返还给你,但是这个样会耗费比较长的时间,但是如果在查询之前,就知道关键词已经存在哪些网页中,这样的话那查询的效率会更加的快速。

在本文章中通过mapreduce实现倒排索引的:
数据例子如下:
Facebook is very good and very nice
Google is very good too
Tencent is very good too

所要实现的效果:
Facebook 第1行数据,索引位置0 :1;
Google 第2行数据,索引位置0 :1;
Tencent 第3行数据,索引位置0 :1;
and 第1行数据,索引位置4 :1;
good 第1行数据,索引位置3 :1;第2行数据,索引位置3 :1;第3行数据,索引位置3 :1;
is 第1行数据,索引位置1 :1;第2行数据,索引位置1 :1;第3行数据,索引位置1 :1;
nice 第1行数据,索引位置6 :1;
too 第2行数据,索引位置4 :1;第3行数据,索引位置4 :1;
very 第1行数据,索引位置2 :1;第1行数据,索引位置5 :1;第2行数据,索引位置2 :1;第3行数据,索引位置2 :1;

整个项目的结构如下:

InvertedIndexKeyValue : 存放map和reduce中间输出变量的函数(这里只实现了map的中间比变量)
InvertedIndexMain:整个项目的入口函数,实现配置map和reduce类的入口
InvertedIndexMapper:项目的map过程
InvertedIndexReducer:项目的reduce过程

项目目录结构.png

分开介绍各个函数的结构:

InvertedIndexKeyValue:主要是定义带有中文描述的数据结构,为map的中间结果使用,当然这里面也可以添加reduce的中间结果,依据需求添加;

package InvertedIndex;

public class InvertedIndexKeyValue {
    //切分单词,形成相应的倒排索引的模式数据
    private String keywords;  //定义map中间结果的key
    private String describe;  //定义map中间结果的 value
    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }
    public void setDescribe(String describe) {
        this.describe = describe;
    }
    public String getKeywords() {
        return keywords;
    }
    public String getDescribe() {
        return describe;
    }
}

InvertedIndexMapper:实现map的过程,主要数统计文件中每一行的数据中单词出现的词频,形成<key,value>的键值对;其中key的构成带有两部分:单词+单词位于第几行中出现;

package InvertedIndex;

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.ObjectWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

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

public class InvertedIndexMapper {
    private static Text text= new Text();

    public static InvertedIndexKeyValue AnalysisKeyWord(String keyword,String i,String j){
        //分开英文单词的函数,以空格进行分词的操作
        InvertedIndexKeyValue invertedIndexKeyValue=new InvertedIndexKeyValue();
        invertedIndexKeyValue.setKeywords(keyword+":"+"第"+i+"行数据,索引位置"+j+" ");
        invertedIndexKeyValue.setDescribe("1");
        return invertedIndexKeyValue;
    }

    public static void delfile(Configuration conf, Path path) throws Exception{
        //每次重复执行之前对相应目录进行清除的操作,确保程序正常执行
        FileSystem fs =FileSystem.get(new URI(path.toString()),conf);
        Path fspath = path;
        if(fs.exists(fspath)){
            fs.delete(fspath,true);
        }
    }

    public static class MapIndex extends Mapper<LongWritable,Text,Text,Text>{
        //先执行计数的过程
        private Text valueof = new Text();
        private Text keyof = new Text();
        private int i=1;
        protected void map(LongWritable key, Text text, Context context) throws IOException, InterruptedException{
            StringTokenizer stringTokenizer = new StringTokenizer(text.toString());
            int index =0; //每个单词位于每一行的数据的索引位置
            while(stringTokenizer.hasMoreTokens()){
                //对每一行进行处理的过程
                InvertedIndexKeyValue invertedIndexKeyValue=InvertedIndexMapper.AnalysisKeyWord(stringTokenizer.nextToken(),String.valueOf(i),String.valueOf(index));
                keyof.set(invertedIndexKeyValue.getKeywords().toString());
                valueof.set(invertedIndexKeyValue.getDescribe().toString());
                context.write(keyof,valueof);
                index++;
            }
            i+=1;
        }
    }
}

InvertedIndexReducer:此函数由两部分构成,Combine和Reduce两个类构成,分别进行reduce的过程;

Combine处理的过程是:map的输出结果的部分,key的形式为:Facebook:第1行数据,索引位置0,而value的形式为1,combine的过程为拆分出“:”之前的单词进行reduce的过程统计值啊每一行上单词出现的词频;
Reduce处理的过程是:把Combine的处理结果按照单词相同和相关描述进行归类,把相关描述按照串联的情况写到一起

package InvertedIndex;

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

import java.io.IOException;

public class InvertedIndexReducer {
    // 完成词频统计的工作
    public static class ReduceIndex extends Reducer<Text,Text,Text,Text>{
        private Text keyindex = new Text();
        private Text valueindex = new Text();
        protected void reduce(Text key,Iterable<Text> value,Context context) throws IOException,InterruptedException{
            StringBuilder stringBuilder = new StringBuilder();
            for (Text va :value){
                stringBuilder.append(va.toString()+";");
            }
            keyindex.set(key);
            valueindex.set(stringBuilder.toString());
            context.write(keyindex,valueindex);
        }
    }

    public static class Combine extends Reducer<Text,Text,Text,Text>{
        private Text keyinfo = new Text();
        private Text valueinfo = new Text();
        protected void reduce(Text key,Iterable<Text> value,Context context) throws IOException,InterruptedException{
            //开始统计词频的过程
            int sum = 0 ;
            for (Text text:value){
                sum += Integer.parseInt(text.toString()); //对value的值进行统计处理
            }
            //重新设计key和value的值,sum座位value的值,对key值进行拆分处理,一部分取出作为value的值进行处理
            int spiltindex = key.toString().indexOf(":");
            keyinfo.set(key.toString().substring(0,spiltindex));
            valueinfo.set(key.toString().substring(spiltindex+1)+":"+sum);
            context.write(keyinfo,valueinfo);
        }
    }
}

InvertedIndexMain:负责的相应的类的调用的过程

package InvertedIndex;

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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class InvertedIndexMain {
    //倒排索引的主函数
    public static void main(String[] args) throws Exception{
        Configuration conf = new Configuration();
        Path path1 = new Path("InvertedIndex/InvertedIndexFile");
        //Path path2 = new Path(args[1]);
        Path path2 = new Path("outputInvertedIndex");
        InvertedIndexMapper.delfile(conf,path2);
        Job job= Job.getInstance(conf,"InvertedIndex");

        FileInputFormat.setInputPaths(job,path1);
        FileOutputFormat.setOutputPath(job,path2);

        job.setJarByClass(InvertedIndexMain.class);

        job.setMapperClass(InvertedIndexMapper.MapIndex.class);
        job.setCombinerClass(InvertedIndexReducer.Combine.class);
        job.setReducerClass(InvertedIndexReducer.ReduceIndex.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        //map函数搞定
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        job.waitForCompletion(true);
    }
}

执行结果.png

PS:hadoop的本地环境的配置参考我上一篇文章!!!

加班过后,熬夜写了今天的学习内容,虽然累,但是觉得还是值得的,为自己加油!!!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容