Hadoop GroupingComparator类用途

Hadoop GroupingComparator类用途,hadoop,mapreduce,Hadoop,Mapreduce,我正在通过一个字符串键实现两个数据集a和B之间的连接,字符串键是name属性。我需要在此联接中匹配相似的名称 我的第一个想法是,考虑到我正在实现二次排序以在数据库B中的值之前获取从数据库A中提取的值,我的第一个想法是创建一个分组比较器类,而不是使用compareTo方法按自然键对值进行分组,而是使用字符串相似性算法,但它没有按预期工作。请参阅下面的代码 public class StringSimilarityGroupingComparator extends WritableComparat

我正在通过一个字符串键实现两个数据集a和B之间的连接,字符串键是name属性。我需要在此联接中匹配相似的名称

我的第一个想法是,考虑到我正在实现二次排序以在数据库B中的值之前获取从数据库A中提取的值,我的第一个想法是创建一个分组比较器类,而不是使用compareTo方法按自然键对值进行分组,而是使用字符串相似性算法,但它没有按预期工作。请参阅下面的代码

public class StringSimilarityGroupingComparator extends WritableComparator {

protected StringSimilarityGroupingComparator() {
    super(JoinKeyTagPairWritable.class, true);
}

public int compare(WritableComparable w1, WritableComparable w2) {
    JoinKeyTagPairWritable k1 = (JoinKeyTagPairWritable) w1;
    JoinKeyTagPairWritable k2 = (JoinKeyTagPairWritable) w2;
    StringSimilarityMatcher nameMatcher = new StringSimilarityMatcher(
            StringSimilarityMatcher.NAME_MATCH);

    return nameMatcher.match(k1.getJoinKey(), k2.getJoinKey()) ? 0 : k1
            .getJoinKey().compareTo(k2.getJoinKey());
}
这种方法对我来说完全有意义。我哪里弄错了?这不是重写分组比较器类的目的吗

编辑:

我知道我需要编写一个自定义分区程序来保证相似的键被发送到同一个reducer,但是由于我处理的是一个相对较小的数据库,所以只有一个reducer就可以很好地运行该任务

为了澄清我所面临的问题,我使用一个identity reducer运行了这个作业,以公开哪些键被分组在一起,我将发出key和dataset标记。以下是输出的示例:

Ricardo 0
Ricardo 1
Ricardo 1
Ricardo Beguer 1
END OF REDUCE METHOD

Ricardo Castro 1
END OF REDUCE METHOD

Ricardo S.(Gueguel) 1
Ricardo Silva 1
END OF REDUCE METHOD

Ricardo tsubasa 1
Ricardo! 1
RicardoRoale 1
END OF REDUCE METHOD
所有这些名称都使用我的算法进行匹配,但它们没有分组在一起。我不明白为什么会发生这种情况,因为我不知道MapReduce如何使用我的分组比较器类对键进行分组

标记为0的数据集是联接的左侧数据库,所以,我希望数据集1中的所有相似名称都使用数据集0中的名称分组

您可以定义MapReduce如何进行此分组吗?它是经过排序和迭代的吗

我见过很多人在处理匹配相似名称的问题时谈论集合相似性(例如),但这种方法似乎更简单,也更有效,因为名称不是大字符串,匹配由分组比较器类完成,只需要一项工作


提前谢谢

您没有描述您的解决方案无法正常工作的方式,但根据您的演示,我可以提出一些建议

我看到的第一个问题是,您不能保证相似的名称被发送到同一个减速机。例如,我希望“Chris”和“Christopher”在您的名字matcher中可以比较为相同,但您不能保证键“Chris”与键“Christopher”被发送到相同的减速机。如果使用默认的分区器,则很可能为hashcode为65087095的“Chris”分配的减缩器与hashcode为1731528407的“Christopher”分配的减缩器不同

为了正确性和性能,我建议您尝试规范化映射器中的每个名称,以便映射器可以编写:

"Christopher" -> value
你应该让他们写:

"Chris"  ->   "Christopher" + original value
其中,“Chris”是所有类似名称的规范化形式(“Chris”、“Christopher”、“Christophe”等)。通过这种方式,默认的分区器和分组器将正常工作,并且您将使用所需的传递的键/值数据获得所需的分组

你可能还遇到了一个更困难的问题,那就是像“克里斯”这样的名字实际上可能与两个本身并不相似的名字相似,比如“克里斯托弗”和“克里斯汀”。如果是这样的话,事情就会变得非常棘手。解决方案仍然可行,但您可能需要更多信息(例如性别)来规范化姓名,或者您可能必须接受错过的匹配。我可以详细说明你的情况

--编辑--

为了回答你的澄清。。。在键/值对被传递到减速机之前,有两个分类器用于键/值对。第一种方法对键进行排序,如果没有指定grouper,则根据唯一的键值调用reducer。如果指定了一个grouper,那么grouper只用于比较“相邻键”(按照第一个排序),以查看它们是否应该传递到同一个reducer调用中

例如,假设A1和A2被视为相同的键(例如相似的名称),但B与A1或A2不相似。如果分拣机将钥匙分类为

A1 A2 B
然后,将两次调用reducer,一次调用A1和A2,另一次调用B。但是,如果排序成功生成键序列:

A1 B A2
然后减速器将被调用三次。石斑鱼比较器只比较A1和B,然后比较B和A2

这意味着grouper排序确实应该以与排序器相同的方式比较字符串,但只能使用更多匹配项

用你上面的例子来说,石斑鱼似乎在比较“里卡多·贝格尔”和“里卡多·卡斯特罗”,发现它们并不相似。尽管“里卡多”可能与“里卡多·卡斯特罗”相似,但这两者从未被比较过


你能把所有的名字相互比较一下,看看是否有一对不相似吗?

我认为克里斯是对的。您可能违反的主要规则是

If A < B (via sort) then A <= B (via grouper)
If A = B (via sort) then A = B (via grouper)

如果A