您的位置:首页 > 其它

MapReduce 简单的全文搜索2

2015-06-01 10:27 225 查看
上一个全文搜索实现了模糊查找,这个主要实现了精确查找,就是比如你查找mapreduce is simple那么他就只查找有这个句子的文章,而不是查找有这三个单词的文章。
这个版本需要重写反向索引,因为需要查找句子,所以需要定位每个单词的在文章中的位置,所以我们的反向索引需要加上单词所在的位置,即我们希望的输出是:
MapReduce file1.txt:<1,2,3>;file2.txt:<5,3,1>;这种格式的。
其实这一步比较简单。我们在map的时候输出为
“filename+word” position这样的<key,value>
“file1.txt:MapReduce”1
经过本地的combiner将其输出为:
“filename” “word:<position>”
"file1.txt" "MapReduce:<1,2,3>"
最后经过reduece将所有同一个文件的单词归一,输出为
"filename" "word1:<position>;word2:<position>...."
"file1.txt" "MapReduce:<1,2,3>;simple:<5,6,7>"这种格式的
PS:由于这里的读取是从文件中每次读取一行,所以这里的position只是每一行上的位置,为非该单词在全文中的位置,如果遇到一句话横跨两行,那么这个程序就无法识别了,好像需要重写那个Input了,等下一个版本再修改

接下来主要就是根据索引来查找
大致的思路就是
Map阶段通过需要查找的句子例如MapReduce is simple来筛选反向索引中的单词,最后经过Map后得到在被查找的句子中的单词。输出为:
"filename" "word<position>"
"file1.txt" "MapReduce<1,2,3>"
经过reduce,则会把所有相同的文件的word给放在一起。由于reduce中单词的顺序是混乱的,所以为了识别句子,我这里增加了一个类
[align=left]class Address implements Comparable<Address>{[/align]
[align=left] public String word ;[/align]
[align=left] public int index;[/align]
[align=left] Address(String word, int index){[/align]
[align=left] this.word =word;[/align]
[align=left] this.index =index;[/align]
[align=left] }[/align]
[align=left] public String toString(){[/align]
[align=left] return word +" "+ index;[/align]
[align=left] }[/align]
[align=left] public int compareTo(Address a){[/align]
[align=left] if(index <a.index) return -1;[/align]
[align=left] else return 1;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]主要的word是用于放单词,index用于放索引,通过将同一个file下的value拆分到Address中,并且按照index进行排序,那么我们就能获得例如[/align]
[align=left]M 1[/align]
[align=left]M 2[/align]
[align=left]M 3[/align]
[align=left]i 4[/align]
[align=left]s 5[/align]
[align=left]i 6[/align]
[align=left]M 7[/align]
[align=left](M代表Mapreduce i代表is,s代表simple)[/align]
[align=left]那么如何识别这里的句子呢,首先这里的index必须是相邻的,并且这相邻的单词的顺序必须是M i s。为了识别相邻的单词的顺序问题,我这里新建了一个list,用于放输入的参数,也就是我要查找的句子,[/align]

[align=left]ArrayList<String> sentence= new ArrayList<String>();[/align]
[align=left] for (i=2;i<wordnum+2;i++){[/align]
[align=left] String arg=conf.get("args" +i);[/align]
[align=left] sentence.add(arg);[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left]接下来我们建立两个游标,一个指向上一个 word position一个指向当前,如果说上一个的word和当前的word在sentence中的位置刚好是相邻的,并且两个index也是相邻的那么n++,接着这两个游标都往下一步走,继续判断,直到n等于句子中单词的长度,那就说明已经匹配到了一个完整的句子。接着n=1再继续往下走,直到遍历完[/align]
[align=left]具体代码:[/align]
[align=left] [/align]

[align=left]public class MyMapper extends Mapper<LongWritable, Text, Text, Text> {[/align]
[align=left] [/align]
[align=left] public void map(LongWritable ikey, Text ivalue, Context context)[/align]
[align=left] throws IOException, InterruptedException {[/align]
[align=left] Configuration conf=context.getConfiguration();[/align]
[align=left] ArrayList< String> contents=new ArrayList< String>();[/align]
[align=left] int agrsnum=Integer.parseInt(conf.get( "argsnum"));[/align]
[align=left] int i=0;[/align]
[align=left] for (i=2;i<agrsnum;i++){[/align]
[align=left] String arg=conf.get("args"+i);[/align]
[align=left] contents.add(arg);[/align]
[align=left] }[/align]
[align=left] String line=ivalue.toString();[/align]
[align=left] String key=line.split(" ")[0];[/align]
[align=left] String value=line.split(" ")[1];[/align]
[align=left] for(String content:contents){[/align]
[align=left] if(content.compareTo(key)==0){[/align]
[align=left] StringTokenizer st=new StringTokenizer(value,";" );[/align]
[align=left] while(st.hasMoreTokens()){[/align]
[align=left] String s=st.nextToken();[/align]
[align=left] String filename=s.split(":")[0];[/align]
[align=left] String adds=s.split(":")[1];[/align]
[align=left] String val=key+adds;[/align]
[align=left] //System.out.println(filename+" "+ val);[/align]
[align=left] [/align]
[align=left] //System.out.println(" ");[/align]
[align=left] context.write( new Text(filename),new Text(val));[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left]}[/align]

[align=left] [/align]
[align=left] [/align]
[align=left] [/align]

[align=left]class Address implements Comparable<Address>{[/align]
[align=left] public String word ;[/align]
[align=left] public int index;[/align]
[align=left] Address(String word, int index){[/align]
[align=left] this.word =word;[/align]
[align=left] this.index =index;[/align]
[align=left] }[/align]
[align=left] public String toString(){[/align]
[align=left] return word +" "+ index;[/align]
[align=left] }[/align]
[align=left] public int compareTo(Address a){[/align]
[align=left] if(index <a.index) return -1;[/align]
[align=left] else return 1;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]public class MyReducer extends Reducer<Text, Text, Text, Text> {[/align]
[align=left] [/align]
[align=left] public void reduce(Text _key, Iterable<Text> values, Context context)[/align]
[align=left] throws IOException, InterruptedException {[/align]
[align=left] // process values[/align]
[align=left] Configuration conf=context.getConfiguration();[/align]
[align=left] int wordnum=Integer.parseInt(conf.get( "argsnum"))-2;[/align]
[align=left] int i=0;[/align]
[align=left] ArrayList<String> sentence= new ArrayList<String>();[/align]
[align=left] for (i=2;i<wordnum+2;i++){[/align]
[align=left] String arg=conf.get("args" +i);[/align]
[align=left] sentence.add(arg);[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] ArrayList<Address> list= new ArrayList<Address>();[/align]
[align=left] [/align]
[align=left] for (Text val : values) {[/align]
[align=left] String[] line=val.toString().split("<|>|," );[/align]
[align=left] for(int j=1;j<line.length;j++){[/align]
[align=left] Address a=new Address(line[0],Integer.parseInt(line[j]));[/align]
[align=left] list.add(a);[/align]
[align=left] }[/align]
[align=left] i++;[/align]
[align=left] }[/align]
[align=left] Collections. sort(list);[/align]
[align=left] [/align]
[align=left] for(Address x:list){[/align]
[align=left] System. out.println(x);[/align]
[align=left] System. out.println(" " );[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] int sum=0;[/align]
[align=left] int n=1;[/align]
[align=left] Address start=list.get(0);[/align]
[align=left] for(i=0;i<list.size();i++){[/align]
[align=left] Address now=list.get(i);[/align]
[align=left] if(sentence.indexOf(now.word )-sentence.indexOf(start.word)==1&&now. index-start.index ==1){[/align]
[align=left] n++;[/align]
[align=left] start. word=now.word ;[/align]
[align=left] start. index=now.index ;[/align]
[align=left] } else{[/align]
[align=left] n=1;[/align]
[align=left] start. word=now.word ;[/align]
[align=left] start. index=now.index ;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] if(n==wordnum){[/align]
[align=left] System. out.println("match is " +now);[/align]
[align=left] sum++;[/align]
[align=left] n=1;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] [/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] /*[/align]
[align=left] for (i=0;i<list.size()-2;i++){[/align]
[align=left] Address t1=list.get(i);[/align]
[align=left] Address t2=list.get(i+1);[/align]
[align=left] Address t3=list.get(i+2);[/align]
[align=left] if((t1.index+2)==t3.index&&(t2.index+1)==t3.index){[/align]
[align=left] if(t1.add!=t2.add&&t1.add!=t3.add&&t2.add!=t3.add){[/align]
[align=left] sum++;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] [/align]
[align=left] System.out.println(" ");[/align]
[align=left] System.out.println("sum is "+sum);[/align]
[align=left] System.out.println(" ");[/align]
[align=left] */[/align]
[align=left] if(sum>0){[/align]
[align=left] context.write(_key, new Text(String.valueOf(sum)));[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left]}[/align]

[align=left] [/align]
[align=left] [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: