Hadoop 多个输入



我正在使用hadoop映射reduce,我想计算两个文件。我的第一次 Map/Reduce 迭代给了我一个带有一对 ID 号的文件,如下所示:

A 30
D 20

我的目标是使用文件中的 ID 与另一个文件关联,并具有具有三个输出的另一个输出:ID、数字、名称,如下所示:

A ABC 30
D EFGH 20

但我不确定使用Map Reduce是否是最好的方法。例如,使用文件读取器读取第二个输入文件并按 ID 获取名称会更好吗?或者我可以用地图减少来做到这一点吗?

如果是这样,我试图找出方法。我尝试了多输入解决方案:

MultipleInputs.addInputPath(job2, new Path(args[1]+"-tmp"),
    TextInputFormat.class, FlightsByCarrierMapper2.class);
MultipleInputs.addInputPath(job2, new Path("inputplanes"),
    TextInputFormat.class, FlightsModeMapper.class); 

但是我想不出任何解决方案可以将两者结合起来并获得我想要的输出。我现在的方式只是给我这样的列表,如这个例子:

A ABC
A 30
B ABCD
C ABCDEF
D EFGH
D 20

在我最后一次减少之后,我得到了这个:

N125DL  767-332
N125DL  7   , 
N126AT  737-76N
N126AT  19  , 
N126DL  767-332
N126DL  1   , 
N127DL  767-332
N127DL  7   , 
N128DL  767-332
N128DL  3

我想要这个:N127DL 7 767-332。而且,我不想要那些不结合的。

这是我的归约类:

公共类 FlightsByCarrierReducer2 扩展 Reducer {

String merge = "";
protected void reduce(Text token, Iterable<Text> values, Context context) 
                            throws IOException, InterruptedException {
    int i = 0;  
    for(Text value:values)
    {
        if(i == 0){
            merge = value.toString()+",";
        }
        else{
            merge += value.toString();
        }
        i++;
    }
        context.write(token, new Text(merge));
}

}

更新:

http://stat-computing.org/dataexpo/2009/the-data.html 这是我正在使用的示例。

我正在尝试:TailNum 和 Cancel,即 (1 或 0( 获取与 TailNuN 对应的模型名称。我的模型文件有一个TailNumb,Model和其他东西。我目前的输出是:

N193JB ERJ 190-100 IGW

N194DN 767-332

N19503 EMB-135ER

N19554 EMB-145LR

N195DN 767-332

N195DN 2

首先是钥匙,其次是模型,航班

取消的钥匙,模型下方的apperas。

我想要一个三重键,取消的型号,因为我希望每个型号的取消次数

您可以使用 ID 作为两个映射器的键来加入它们。您可以将地图任务编写为如下所示

public void map(LongWritable k, Text value, Context context) throws IOException, InterruptedException
{
    //Get the line
    //split the line to get ID seperate
    //word1 = A 
    //word2 = 30
                //Likewise for A ABC
                   //word1 = A 
                  //word2 = ABC
    context.write(word1, word2);
}

我认为您可以重复使用相同的地图任务。然后编写一个commomn Reducer作业,其中Hadoop框架在关键基础上对数据进行分组。因此,您将能够获得ID作为密钥。您可以缓存其中一个值,然后进行连接。

String merge = "";
public void reduce(Text key, Iterable<Text> values, Context context)
{
    int i =0;
    for(Text value:values)
    {
        if(i == 0){
            merge = value.toString()+",";
        }
        else{
            merge += value.toString();
        }
        i++;
    }
    valEmit.set(merge);
    context.write(key, valEmit);
}

最后,您可以编写驱动程序类

public int run(String[] args) throws Exception {
 Configuration c=new Configuration();
 String[] files=new GenericOptionsParser(c,args).getRemainingArgs();
 Path p1=new Path(files[0]);
 Path p2=new Path(files[1]);
 Path p3=new Path(files[2]);
 FileSystem fs = FileSystem.get(c);
 if(fs.exists(p3)){
  fs.delete(p3, true);
  }
 Job job = new Job(c,"Multiple Job");
 job.setJarByClass(MultipleFiles.class);
 MultipleInputs.addInputPath(job, p1, TextInputFormat.class, MultipleMap1.class);
 MultipleInputs.addInputPath(job,p2, TextInputFormat.class, MultipleMap2.class);
 job.setReducerClass(MultipleReducer.class);
 .
 .
}

你可以在这里找到这个例子

希望这有帮助。


更新

输入1

A 30
D 20

输入2

A ABC
D EFGH

输出

A ABC 30
D EFGH 20

映射器.java

import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
 * @author sreeveni
 *
 */
public class Mapper1 extends Mapper<LongWritable, Text, Text, Text> {
    Text keyEmit = new Text();
    Text valEmit = new Text();
    public void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        String line = value.toString();
        String parts[] = line.split(" ");
        keyEmit.set(parts[0]);
        valEmit.set(parts[1]);
        context.write(keyEmit, valEmit);
    }
}

减速机.java

import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
 * @author sreeveni
 *
 */
public class ReducerJoin extends Reducer<Text, Text, Text, Text> {
    Text valEmit = new Text();
    String merge = "";
    public void reduce(Text key, Iterable<Text> values, Context context)
            throws IOException, InterruptedException {
        String character = "";
        String number = "";
        for (Text value : values) {
            // ordering output
            String val = value.toString();
            char myChar = val.charAt(0);
            if (Character.isDigit(myChar)) {
                number = val;
            } else {
                character = val;
            }
        }
        merge = character + " " + number;
        valEmit.set(merge);
        context.write(key, valEmit);
    }
}

驱动程序类

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.MultipleInputs;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
 * @author sreeveni
 *
 */
public class Driver extends Configured implements Tool {
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        // checking the arguments count
        if (args.length != 3) {
            System.err
                    .println("Usage : <inputlocation>  <inputlocation>  <outputlocation> ");
            System.exit(0);
        }
        int res = ToolRunner.run(new Configuration(), new Driver(), args);
        System.exit(res);
    }
    @Override
    public int run(String[] args) throws Exception {
        // TODO Auto-generated method stub
        String source1 = args[0];
        String source2 = args[1];
        String dest = args[2];
        Configuration conf = new Configuration();
        conf.set("mapred.textoutputformat.separator", " "); // changing default
                                                            // delimiter to user
                                                            // input delimiter
        FileSystem fs = FileSystem.get(conf);
        Job job = new Job(conf, "Multiple Jobs");
        job.setJarByClass(Driver.class);
        Path p1 = new Path(source1);
        Path p2 = new Path(source2);
        Path out = new Path(dest);
        MultipleInputs.addInputPath(job, p1, TextInputFormat.class,
                Mapper1.class);
        MultipleInputs.addInputPath(job, p2, TextInputFormat.class,
                Mapper1.class);
        job.setReducerClass(ReducerJoin.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);
        job.setOutputFormatClass(TextOutputFormat.class);
        /*
         * delete if exist
         */
        if (fs.exists(out))
            fs.delete(out, true);
        TextOutputFormat.setOutputPath(job, out);
        boolean success = job.waitForCompletion(true);
        return success ? 0 : 1;
    }
}

您的化简器有一个映射方法,但它应该有一个 reduce 方法,该方法采用可迭代的值集合,然后合并这些值。 因为你没有 reduce(( 方法,所以你会得到默认行为,即只传递所有的键/值对。

相关内容

  • 没有找到相关文章

最新更新