#博学谷IT技术支持#
本篇文章描述了用MapReduce实现一个sql中的join操作过程,包含了Reduce端join和分组。
一、需求
有两张表,分别为订单表itheima_order_goods和商品表itheima_goods,要求实现将每个订单购买的商品信息放在订单后面作为一行输出。
订单表组成:订单id|商品id|商品价格
商品表组成:商品id|商品数量|商品名称
二、思路
订单表
k1:行偏移量
v1:订单表一行
k2:商品id
v2:订单表一行
商品表
k1:行偏移量
v1:商品表一行
k2:商品id
v2:商品表一行
分组后相同k2合并,v2为购买了相同商品的订单信息及购买的商品信息,需要将不同的订单信息和商品信息提取作为k3,v3为NullWritable。
三、代码实现
map方法
获取读取的文件名称分别处理k2和v2,因为两张表的key均为商品id,为了区分在订单表的v2前面加上o_,在商品表的v2前面加上g_,方便后续处理。
public class ReduceJoinMapper extends Mapper<LongWritable, Text, Text, Text> {
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context) throws IOException, InterruptedException {
FileSplit fileSplit = (FileSplit) context.getInputSplit();
String fileName = fileSplit.getPath().getName();
String[] array = value.toString().split("\\|");
if ("itheima_order_goods.txt".equals(fileName)) {
String k2 = array[1];
String v2 = "o_" + array[0] + "\t" + array[2];
context.write(new Text(k2), new Text(v2));
}
if ("itheima_goods.txt".equals(fileName)) {
String k2 = array[0];
String v2 = "g_" + array[0] + "\t" + array[2];
context.write(new Text(k2), new Text(v2));
}
}
}
reduce方法
将v2中订单信息提取放入集合中,分组后每一条中只有一个商品信息,因此将商品信息单独作为字符串保存,输出的k3为将集合中的信息与商品信息合并。
public class ReduceJoinReducer extends Reducer<Text, Text, Text, NullWritable>{
@Override
protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, NullWritable>.Context context) throws IOException, InterruptedException {
ArrayList<String> orderList = new ArrayList<>();
String goods_value = "";
for (Text value : values) {
if (value.toString().startsWith("o_")) {
orderList.add(value.toString().substring(2));
}
if (value.toString().startsWith("g_")) {
goods_value = value.toString().substring(2);
}
}
for (String order_value : orderList) {
context.write(new Text(order_value + "\t" + goods_value), NullWritable.get());
}
}
}
排序
将相同的订单id放在一起输出
public static class ReduceJoinSortMapper extends Mapper<LongWritable, Text, Text, Text> {
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context) throws IOException, InterruptedException {
context.write(new Text(value.toString().split("\t")[0]), value);
}
}
public static class ReduceJoinSortReducer extends Reducer<Text, Text, Text, NullWritable> {
@Override
protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, NullWritable>.Context context) throws IOException, InterruptedException {
for (Text value : values) {
context.write(value, NullWritable.get());
}
}
}
四、运行结果
每行结果为订单id,商品价格,商品id,商品名称,前两个为订单表中内容,后两个为商品表中内容。