地图降低适用性

时间:2013-01-02 19:25:59

标签: mongodb mapreduce

我有一个关于map / reduce的问题,以及它是否适合我正在努力完成的任务。我还处于设计阶段,所以如果需要,我可以改变数据的结构。

想象一下,我有两个这样的文件:

{ "_id" : ObjectId( "50231b4f8be6e5f1f2e7e24g" ),
  "customer" : "50bac36bb4e54678170002e6",
  "display" : "Motorola Canopy 100",
  "description" : "a radio" }

{ "_id" : ObjectId( "50232fac8be6e4f1f2e7e259" ),
  "display" : "Motorola POE",
  "description" : "a power injector",
  "device" : "50231b4f8be6e4f1f2e7e24g" }

在一个文档上,有一个客户ID引用(“customer”:“50bac36bb4e54678170002e6”),另一个文档中有一个设备ID引用(“device”:“50231b4f8be6e4f1f2e7e24g”)。这两个文件都代表某种设备。该设备将与客户相关(也称为,分配)或与另一设备相关。例如,客户将获得一台收音机,它将被分配,但电源注入器将分配给收音机本身,而不是客户。我这样做了,所以我可以更好地理解设备之间的操作依赖性。保持这种分层关联模式很有用,如果可能的话我想保留它。

我目前运行一系列查询,首先查找所有设备,然后对于找到的每个设备,运行另一个查询以查找相关设备。这是一个递归操作,可以与任何给定设备的关联一样深。

我很想知道这个问题是否适合map / reduce操作。我应该坚持使用我当前的递归操作还是这是一个很好/完美适合map / reduce?

编辑1

进一步澄清评论中提出的问题:

  1. 所有这些文件都在同一个集合中是真的吗? 有一个“设备”集合。但客户ID来自不同的集合。但是,出于此查询的目的,我只使用该ID对设备集合中的结果进行分组。没有“加入”,借用一个sql术语,已经完成,也不需要它们。将客户密钥和设备密钥视为应该排序的属性。
  2. 另外,您说您运行查询以“查找所有设备”。您的意思是“找到所有给定客户ID的设备吗?” :执行的第一个查询是基于密钥的客户ID。它基本上是这样的:db.devices.find({“customer”:“50bac36bb4e54678170002e6”})。然后我接受该结果并迭代它,使用直接的javascript来对哈希进行排序并触发子查询。然后我留下了一些新的查询来运行,基本上所有用第一个查询捕获的_id都会被查询到这样的东西:db.devices.find({_ id:“50bac36bb4e54678170002e6”})。该查询将生成在第一次查询期间未发现的新文档。我继续此子查询步骤,直到db.devices.find不产生任何新结果。然后我在这些结果上运行更多的javascript并将它们合并到第一个,构建一个哈希树。这就是我知道如何构建树的方法。
  3. 每个设备都“向上”流向一个客户是真的吗?的
  4. 设备是否可能属于多个父设备或客户?的 没有

2 个答案:

答案 0 :(得分:3)

MapReduce最适用于没有依赖关系的文档。如果您的数据结构只是一个有向无环图(DAG),其中每个客户都是根节点,并且每个设备可能有多个父节点。由于依赖关系,Map / Reduce不适合大多数DAG操作。

但是,由于您的数据是树状的(没有多父母),您可以add an array of ancestors as in the MongoDB docs example。在这种情况下,MR可能非常适合某些操作。

如果我理解你的查询策略,我担心在每个递归级别的内部循环中执行大量查询操作的效率。为了帮助实现这一点,理想情况下,“device”应该是ObjectId类型而不是字符串,并且应该对其进行索引。索引的替代方法也可以是store the children ObjectId's as child references per this MongoDB docs example。在任何一种情况下,为每个递归级别运行MR或“$ group”聚合操作都可能有所帮助,但我怀疑在大多数情况下它只会将计算从DB客户端转移到DB服务器。

答案 1 :(得分:1)

我不认为map / reduce在这里是一个很好的解决方案,因为数据是相互依赖的,这使得并发无效。或者,您可以使用dbRef嵌入相关设备,以便可以直接从相关设备文档中访问它。