我是map-reduce编码的新手。我请求帮助编写reducer代码来找不到。按部门名称划分的女性员工。
我有两个结构化数据文件。一个用于员工,另一个用于部门。在员工档案中,我有" Empid"," Empname"," Empgender"," EmpDeptId"和#34; Empsalary"。在第二个部门文件中,我有" DepId"和"部门名称"。现在我想通过每个部门名称找出FEMALE员工的数量。
我已经编写了一个EmpMapper,我将返回密钥作为DeptId(IntWritable)而不是。发生,即迭代(作为文本)作为值。 e.g。
(1,[1])
(2,[1])
(3,[1])
(4,[1])
(1,[1])

之后洗牌&排序阶段输出如下:
(1,[1,1])
(2,[1])
(3,[1])
(4,[1])

同样来自DeptMapper我将返回以下输出(键为DeptId(IntWritable)和DeptName(作为Text)作为值):
(1,[IT])
(2,[Comsc])
(3,[Electrical])
(4,[Mechanical])

现在我担心的是我无法正确编写减速器。我想将reducer输出返回为
(IT,2)
(Comsc,1)
(Electrical,1)
(Mechanical,1)

请帮我处理reducer代码(需要一种连接)。
答案 0 :(得分:0)
在MapReduce中编写联接非常麻烦。如果您已经有结构化(关系)数据,那么考虑一个允许您编写SQL查询的高级框架(例如Hive)可能是有意义的。
答案 1 :(得分:0)
它基本上是一个减少边连接,在Reducer端创建一个Departments的地图,并且每个Employee都使用这个Map得到每个Employee的Department,并且在这个main之后有一个单独的数据结构来计算。
答案 2 :(得分:0)
你的reducer有key = IntWritable,value = Text。因此,您可以轻松地将它们连接在一起,但是当您获得计数时,我会解决您的类型问题(例如" 1"," 1"以及部门名称和#34; IT& #34)。
一种简单的方法是检查您的文本是否为int,如果您遇到解析错误,则可以认为它是您的部门名称。
也许在代码之下(尽管有些hacky)可能会帮助您找到解决方案:
@Override
protected void reduce(Text key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
String departmentName = null;
int sum = 0;
for (Text value : values) {
String unknown = value.toString();
try {
int valueCount = Integer.parseInt(unknown);
sum += valueCount;
} catch (NumberFormatException e) {
departmentName = unknown;
}
}
assert departmentName != null;
context.write(new Text(departmentName), new IntWritable(sum));
}
我不喜欢使用流量控制的例外,但请在这里务实。
小工作改善:
MultipleInputs
类将其作为单个作业执行