反向索引主要用于全文搜索,就是形成一个word url这样的结构
file1:
MapReduce is simple
file2:
MapReduce is powerful is simple
file3:
Hello MapReduce bye MapReduce
那么经过反向索引后就是:
Hello file3.txt:1;
MapReduce file3.txt:2;fil1.txt:1;fil2.txt:1;
bye file3.txt:1;
is fil1.txt:1;fil2.txt:2;
powerful fil2.txt:1;
simple fil2.txt:1;fil1.txt:1;
MapReduce file3.txt:2;fil1.txt:1;fil2.txt:1;
bye file3.txt:1;
is fil1.txt:1;fil2.txt:2;
powerful fil2.txt:1;
simple fil2.txt:1;fil1.txt:1;
主要的方法就是,对每个文件的内容进行遍历,形成的key为word+filename,value=1然后在combiner中将key相同的进行累加,这样就得到在同一个文件中word的字数了。最后在reduce中将filename进行分割即可。不过这里有个小的bug,一般来说combiner是在同一个节点上进行reduce,但是我这里却是用于统计同一个文件了,如果说文件很大,那么很有可能一个文件的内容会被分配到两个不同的节点上,那么就有会bug了。所以这里只能适合小的文件。
PS:获得文件名String filename = ((FileSplit) context.getInputSplit()).getPath().getName();别的似乎没有了。
public class MyMapper extends Mapper<LongWritable, Text, Text, Text> {
public void map(LongWritable ikey, Text ivalue, Context context)
throws IOException, InterruptedException {
StringTokenizer st= new StringTokenizer(ivalue.toString());
FileSplit split=new FileSplit();
split = (FileSplit) context.getInputSplit();
InputSplit isplit=context.getInputSplit();
String filename = ((FileSplit) context.getInputSplit()).getPath().getName();
while(st.hasMoreTokens()){
//int splitIndex = split.getPath().toString().indexOf("file");
String key=st.nextToken()+":" +filename;
context.write( new Text(key),new Text("1"));
}
}
}
public class MyCombiner extends Reducer<Text, Text, Text, Text> {
public void reduce(Text _key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
// process values
int sum=0;
for (Text val : values) {
sum++;
}
StringTokenizer st= new StringTokenizer(_key.toString(),":");
String key=st.nextToken();
String value=st.nextToken();
value=value+ ":"+sum;
context.write( new Text(key),new Text(value));
}
}
public class MyReducer extends Reducer<Text, Text, Text, Text> {
public void reduce(Text _key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
// process values
String filelist= new String();
for (Text val : values) {
filelist=filelist+val.toString()+ "; ";
}
context.write(_key, new Text(filelist));
//System.out.println(_key.toString()+filelist);
}
}