1

我有一个关于 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 对哈希进行排序并触发子查询。然后我剩下一些要运行的新查询,基本上所有使用第一个查询捕获的 _ids 都会使用以下内容进行查询:db.devices.find({_id:"50bac36bb4e54678170002e6"})。该查询将产生在第一次查询期间未发现的新文档。我继续这个子查询步骤,直到 db.devices.find 没有产生任何新结果。然后我在这些结果上运行更多的 javascript 并将它们合并到第一个中,构建一个哈希树。这就是我知道如何构建树的方式。
  3. 每个设备都“向上”流向一个客户是真的吗?是的
  4. 设备是否可能属于多个父设备或客户?
4

2 回答 2

3

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

但是,由于您的数据是树状的(没有多个父项),您可以添加一个祖先数组,如 MongoDB 文档示例中所示。在这种情况下,MR 可能非常适合某些操作。

如果我了解您的查询策略,我会担心在每个递归级别的内部循环中执行大量查询操作的效率。为了帮助实现这一点,理想情况下,“设备”应该是 ObjectId 类型而不是字符串,并且应该被索引。索引的替代方法也可以将子 ObjectId 存储为每个 MongoDB 文档示例的子引用。在这两种情况下,为每个递归级别运行 MR 或“$group”聚合操作可能会有所帮助,但我怀疑在大多数情况下,它只会将计算从 DB 客户端转移到 DB 服务器。

于 2013-01-03T06:25:40.203 回答
1

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

于 2013-01-03T02:53:57.697 回答