挣扎着简单的hadoop map减少了代码任务

时间:2013-12-12 11:29:30

标签: hadoop mapreduce

我是hadoop世界的新手,并且正在努力完成一项简单的任务而没有找到方法。

我们有一种情况,其中有不同的客户呼叫不同的 人(与不同的移动运营商)。每个电话详细信息都有通话开始时间 日期,与日期的呼叫结束时间,已拨打电话的各种运营商名称。

我们有以下格式的输入文件: 客户电话号码|使用日期开始通话时间|结束与日期的通话时间|
已经拨打电话的各种移动运营商

例如输入文件是这样的:

9898765467| 03:14 12/10/2013 | 03:40 12/10/2013 | airtel 

9898765467| 06:20 12/10/2013 | 07:05 12/10/2013 | vodaphone

9899875321| 08:14 13/10/2013 | 08:40 13/10/2013 | idea

9899875321| 04:15 13/10/2013 | 04:50 13/10/2013 | reliance

9899875321| 09:14 13/10/2013 | 09:30 13/10/2013 | idea

9898765467| 10:20 12/10/2013 | 10:55 12/10/2013 | vodaphone

现在我们想知道每个日期根据哪个手机号码调用哪个手机号码 运营商和通话时间有多长?

就像在给定示例中的9898765467手机号码一样,拨打vodaphone运营商两次 12/10/2013总通话时间为((7:05-6:20)+(10:55-10:20))=45 + 35 = 80 mins

因此手机号码9898765467的输出应该是:

Mobile number | Date  | Operator name | Talk Time

9898765467 | 12/10/2013  | vodaphone | 80 mins

So final output file for all mobile numbers should be like:

9898765467 | 12/10/2013 | vodaphone | 80 mins

9898765467 | 12/10/2013 | airtel     | 26 mins

9899875321 | 13/10/2013 | idea       | 42 mins 

9899875321 | 13/10/2013 | reliance   | 35 mins 

有人可以建议或提供地图缩减代码来完成这项任务吗?

3 个答案:

答案 0 :(得分:3)

首先,您需要为作业(Map-Reduce)确定KeysValues

在这种情况下, 您需要为每个mobileNumber-date-operator组合生成持续时间。

因此, 每行的映射器输出都是,(键 - 上面的组合,值 - 该行的持续时间)。

你的缩减器需要summation持续时间for all这样的唯一键(组合)。

请通过示例来了解逻辑。

由于我主要集中在逻辑部分,您可能需要根据业务需要修改string/date formattingline splits/tokens

package stackoverflow.examples;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

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

public class CallStatsJob {

    public static class CallStatsMapper extends
            Mapper<Object, Text, Text, LongWritable> {
        private LongWritable duration;
        private Text key = new Text();
        private String mobileNumber, startTime, endTime, operator;

        public void map(Object key, Text value, Context context)
                throws IOException, InterruptedException {
            String[] words = value.toString().split(" \\| ");

            mobileNumber = words[0];
            startTime = words[1];
            endTime = words[2];
            operator = words[3];
// for debugging            
//          System.out.println(mobileNumber);
//          System.out.println(startTime);
//          System.out.println(endTime);
//          System.out.println(operator);

            SimpleDateFormat sdf = new SimpleDateFormat("hh:mm dd/M/yyyy");
//          String dateInString = "03:40 12/10/2013";
            Date stDate, enDate;
            try {
                stDate = sdf.parse(startTime);
                enDate = sdf.parse(endTime);
                Long diff = enDate.getTime() - stDate.getTime();
                Long diffMinutes = diff / (60 * 1000);

                this.key = new Text(mobileNumber+"-"+stDate.getDate()+"-"+operator);
                duration = new LongWritable(diffMinutes);

                context.write(this.key, duration);
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }

    }

    public static class CallStatsReducer extends
            Reducer<Text, LongWritable, Text, LongWritable> {
        public void reduce(Text key, Iterable<LongWritable> values,
                Context context) throws IOException, InterruptedException {
            Long sum = 0L;
            for (LongWritable val : values) {
                sum = sum + val.get();
            }
            context.write(key, new LongWritable(sum));

        }
    }

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = new Job(conf, "Caller Statistics");
        job.setJarByClass(CallStatsJob.class);
        job.setMapperClass(CallStatsMapper.class);
        job.setReducerClass(CallStatsReducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        System.exit(job.waitForCompletion(true)?0:1);

    }

}

映射器输出:(如果设置0减速器,您将能够看到此输出)

9898765467-12-airtel    26
9898765467-12-vodaphone 45
9899875321-13-idea      26
9899875321-13-reliance  35
9899875321-13-idea      16
9898765467-12-vodaphone 35

减速机输出:(上述作业的一般输出)

9898765467-12-airtel    26
9898765467-12-vodaphone 80
9899875321-13-idea      42
9899875321-13-reliance  35

我相信这个例子可以为您提供解决方案以及进一步了解的理解。

答案 1 :(得分:0)

使用WordCount Program作为参考。

将地图键设为NUMBER |日期| OPERATOR

将地图值作为持续时间制作。 (你可以找到开始和结束时间之间的差异)

所以映射器在那里结束。

在reducer中,只需总结每个键的持续时间列表。

从减速器发出结果。

答案 2 :(得分:0)

您可以使用没有地图缩减代码的配置单元来实现此目的。 在此文件上创建一个配置单元表。

  

创建外部表callrecords(移动字符串,starttime字符串,endtime字符串,运算符字符串)以'|'结尾的行格式分隔字段以“\ n”位置'tblproperties(“skip.header.line.count”=“1”)终止的行;

通过计算开始和结束时间之间的差异,在表格上创建一个视图create view as selectThis会帮助你计算差异。