我正在编写一个mapReduce作业,该作业从一个巨大的数据集中查找与一点距离最小的k个对象。
在我的映射器中,我只想报告该数据块距离最小的k对象。这样,对于每个数据块,我有k个中间值(key,value),其中key是距离,value是object_id。因此,在我的reducer()中,我可以很容易地处理和总结k个最低值。
我想不出一种方法来只报告我的mapper类中一个数据块的距离最小的k对象的中间键值对?
我知道我可以将该数据块中所有输入数据的(distance,obj_id)作为中间键值对返回,然后在reducer类中减少该值,得到相同的结果。但是k<lt;(每个数据块中的数据数量),并且通过只报告k个中间键值而不是全部,我可以显著减少数据传输/混洗的量。
感谢提供的任何帮助
感谢
假设k很小(您可以在内存中容纳这个数量的对象),那么这应该很容易:
- 创建一个包装器/容器对象,该对象包含两个实例变量——计算的距离(float/double?)和object_id(Text?)
- 有很多可能的方法来维护一组固定的值,但在本例中,让我们使用TreeSet(包装器对象类型)
- 确保包装器对象实现Comparable接口,或者创建一个Comparator实现,TreeSet可以使用该实现来确定顺序-该实现应该首先比较距离实例变量,如果它们相同,然后比较对象ID(这引出了一个有趣的问题——如果你想保留最小的10个值,但有20个值的距离都最小,你想发生什么?你想保留哪10个?)
- 在映射器中处理值时,计算距离值,如果树集大小小于K,或者距离小于树集的尾值距离,然后添加这个distance/obj_id对(如果集合大小小于k,则创建包装器的新实例,或者移除尾值并重新使用它来承载新的distance/obj-id(请确保将其从集合中删除,修改值,然后重新添加)
- 在映射器的清理方法中,一次输出一个值的树集