2015-04-01 203 views
1

我有一個簡單的地圖減少工作,我正在建立反向索引。MapReduce - 減速機不結合鍵

我的映射器正常工作(我檢查),並輸出密鑰對詞和docID的的:TFIDF值:

映射器(只顯示輸出):

context.write(new IntWritable(wordIndex), new Text(index + ":" + tfidf)); 

減速的唯一工作是結合這些價值。這是我的實現:

public static class IndexerReducer extends Reducer<Text, IntWritable, IntWritable, Text> 
    { 
     public void reduce(IntWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException 
     { 

      StringBuilder sb = new StringBuilder(); 

      for (Text value : values) 
      { 
       sb.append(value.toString() + " "); 
      } 

      context.write(key, new Text(sb.toString())); 
     } 
    } 

但是,它沒有組合任何東西,輸出看起來基本上與形成映射器相同。在輸出中有相同的鍵,雖然減速器應該組合它們 - 基本上輸出文件中的所有鍵在使用減速器時應該是唯一的,對嗎?

這是我減速機的輸出如何看起來像一個示例(注意,這是簡化的例子):

1 15:2.1 
1 13:4.3 
2 9:9.3 
2 43:7.9 
etc 

我預計:

1 15:2.1 13:4.3 
2 9:9.3 43:7.9 

爲了完整起見,我包括運行方法:

@Override 
    public int run(String[] arguments) throws Exception { 
     ArgumentParser parser = new ArgumentParser("TextPreprocessor"); 

     parser.addArgument("input", true, true, "specify input directory"); 
     parser.addArgument("output", true, true, "specify output directory"); 

     parser.parseAndCheck(arguments); 

     Path inputPath = new Path(parser.getString("input")); 
     Path outputDir = new Path(parser.getString("output")); 

     // Create configuration. 
     Configuration conf = getConf(); 

     // add distributed file with vocabulary 
     DistributedCache 
       .addCacheFile(new URI("/user/myslima3/vocab.txt"), conf); 

     // Create job. 
     Job job = new Job(conf, "WordCount"); 
     job.setJarByClass(IndexerMapper.class); 

     // Setup MapReduce. 
     job.setMapperClass(IndexerMapper.class); 
     job.setReducerClass(IndexerReducer.class); 

     // Sort the output words in reversed order. 
     job.setSortComparatorClass(WordCountComparator.class); 


     job.setNumReduceTasks(1); 

     // Specify (key, value). 
     job.setMapOutputKeyClass(IntWritable.class); 
     job.setMapOutputValueClass(Text.class); 
     job.setOutputKeyClass(IntWritable.class); 
     job.setOutputValueClass(Text.class); 

     // Input. 
     FileInputFormat.addInputPath(job, inputPath); 
     job.setInputFormatClass(TextInputFormat.class); 

     // Output. 
     FileOutputFormat.setOutputPath(job, outputDir); 
     job.setOutputFormatClass(TextOutputFormat.class); 

     FileSystem hdfs = FileSystem.get(conf); 

     // Delete output directory (if exists). 
     if (hdfs.exists(outputDir)) 
      hdfs.delete(outputDir, true); 

     // Execute the job. 
     return job.waitForCompletion(true) ? 0 : 1; 
    } 

我會很高興任何有關正在發生的提示。我是新來映射減少。感謝您提供任何調試提示!

回答

3

始終使用@Override註釋。

您定義

public static class IndexerReducer extends Reducer<Text, IntWritable, IntWritable, Text> 

然後你減少方法必須看起來像

@Override 
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException 
+0

有趣,沒想到的。我的IDE不讓我這樣做(它產生異常:Indexer.IndexerReducer類型的方法reduce(IntWritable,Iterable ,Reducer .Context)必須覆蓋或實現超類型方法 – Smajl 2015-04-01 15:42:52

+0

正確地說,因爲它是錯誤的。請注意,我爲你換了'key'和'values'類型。 – 2015-04-01 15:44:51

+0

,但是我傳給reducer的那對是,所以IntWritable應該是關鍵字..對吧? – Smajl 2015-04-01 15:46:02

0

@context不org.apache.hadoop.mapreduce.Reducer.Context類型。 我們的Reducer有我們自己的Inner Class類型的上下文。 所以不要使用「org.apache.hadoop.mapreduce.Reducer.Context」,只需使用「上下文」 這將確保@Override可以添加到減少功能沒有錯誤。