是否可以在Mongodb MapReduce中进行Reduce-Side Join

时间:2012-12-31 07:25:23

标签: mongodb mapreduce

我读到Hadoop框架支持Reduce-Side,Replicated和Composite连接等联接。 Mongodb中对这些连接有什么支持吗?

用例对我来说,每个用户都会记录一系列事件及其出现次数。样本是

{_id: uniqueEventId, event: login, userId: abc}

还有另一个集合,其中包含有关用户的详细信息,并且未修复用户的属性。样本文件是

{_id: abc, city: "SF", state: CA, customfield1: value1...}

我需要的结果是事件聚合,userId,还需要填充用户详细信息。样品,

{userId: abc, event: login, count:23, city: SF, state: CA}

这样我就可以根据具有最大登录事件和类似查询的州或城市进行查询。

我考虑将用户文档作为事件文档的一部分嵌入,但如果用户属性发生了变化,我需要更新字面上的所有事件集合,这将是巨大的。

我看了一下从这个link合并两个集合的方法,但这并不是很有用,因为我需要运行reduce函数的键是一个复合键(userId + event)。

1 个答案:

答案 0 :(得分:1)

我想请注意,这个JOIN不能实时用于你的应用程序,通过这样做你打破了MongoDB,但是,是的;有一种方法可以映射 - 减少JOIN。

在你的第一张MR中获得:

{_id: abc, city: "SF", state: CA, customfield1: value1...}

您只需发出此行并将其写入新集合。然后在你的第二个MR中:

{userId: abc, event: login, count:23, city: SF, state: CA}

userId实际_id

var map = function(){
    emit(this.userId, {this.event, //etc});
}

或复合键:

var map = function(){
    emit({o: this.userId, e: this.event}, {this.event, //etc});
}

然后您正常减少但是更改命令,或者更确切地说,呼叫服务器,以便MR中的out选项实际指向您的第一个MR添加reduce或{的结果merge选项上的{1}}命令使两个集合在重复的out上连接:

_id

这基本上就是它的运作方式。

在回答开始时回到我的第一个通知。这不是SQL JOIN,不应该这样对待它们。 JS引擎是:

  • 单线程
  • 实际上不是MongoDB或服务器端,它实际上是MongoDB的内置JS引擎

如果集合失控或者该命令实时运行到您的应用程序,您可以轻松地看到需要在您的服务器上运行的其他JavaScript(请记住它是单线程)的性能问题。

修改

  

这样我就可以根据具有最大登录事件和类似查询的州或城市进行查询。

虽然登录不会发生在那个城市吗?因此,登录行可能包含城市和州字段。这不需要更新,听起来很奇怪,因为登录会在那里发生,而不是其他任何地方:

  

我需要更新字面上的所有事件集合,这将是巨大的。

变得过时,因为登录事件不需要更新,因为它发生在记录的状态/城市中是正确的。

所以我实际上会找到一个架构:

db.col.mapreduce( map, reduce, { out: {merge:collection_from_first_mr} })

并汇总。