MongoDB使用订单字段处理多个对象

时间:2014-07-02 13:03:12

标签: mongodb meteor

让我们想象某种包含许多幻灯片的演示文稿。 mongo中的演示文稿集合可以表示为: { _id: <presentation_id>, author: <author_name>, ... }

还有幻灯片集合,其中包含这些演示文稿的幻灯片: { _id: <slide_id>, presentation_id: <presentation_id>, content: <content(html,text, etc.)>, order: <slide_order (page number)> /* This field is used to place slides in correct order during showcase*/ }

与所有演示文稿一样,幻灯片可以添加,移动,删除等,并且应该在每次操作后自动保存更改。在每个幻灯片添加或移动时使用此类方案,我们需要使用他们的订单值更新大量幻灯片。在流星中,它会导致安静的大等待时间(例如,对于250张幻灯片的演示,如果我们在其开头添加1张幻灯片,我们需要在for循环中更新250张现有幻灯片。)

我还想到了两件事如何解决这个问题: 1)添加到presentation新字段slides,该字段将是按顺序包含幻灯片ID的数组。但是这种方式在排序方面存在问题:现在mongodb不能按ID数组排序结果(在&lt; = 2.4版本中有使用$or的黑客攻击,但在2.6中它不再可用)没有使用聚合框架(它不会出现在流星体中,需要额外的模块)。这将通过一次大更新取代大量的小更新。

2)另一种方法是使用两个新字段替换幻灯片集合中的order字段:prevnext,并仅保存下一张和上一张幻灯片ID。这将减少(重新)移动/添加操作到少量小更新,但是当我需要显示所有幻灯片时,我需要分两步执行此操作:以不正确的顺序从db获取幻灯片,找到第一个(最后一个)使用next / prev&#34;链接&#34;。

滑动并恢复正确的顺序

首选哪种方式?或者可能有另一种更好的方法来做到这一点?

1 个答案:

答案 0 :(得分:1)

最好的方法可能是将幻灯片移动到演示文稿中的数组。

因为在几乎所有用于幻灯片集合的用例中,您都需要来自演示文稿集合的数据。数组始终是有序的,因此您不需要/需要幻灯片的_id字段。

唯一的限制是总演示文稿不能超过16兆字节。

然后,您可以使用mongodb的array update modifiers在集合中移动幻灯片。 $position modifier对添加特别有用。 你可以结合$splice and $push来移动东西。

编辑:在更新中使用$ inc,例如:

在订单中间插入幻灯片:

 col.update({presentation_id:xxx, order:{$gte:20}},{$inc:{order:1}},{multi:true});
 col.insert({order:20, presentation_id:xxx/*otherdata*/});

这增加了从20开始的所有顺序字段,因此必须释放位置20.这使用mongos自己的光标而不是for循环,所以应该是一个快得多的地狱。

移动文档:

 var moveSlide = col.findOne({presentation_id:xxx, order:20});
 col.update({presentation_id:xxx, {order:{$lte:20}}},{$inc:{order:1}},{multi:true});
 col.update(moveSlide._id, {$set:{order:1}});

移动文档:

 var moveSlide = col.findOne({presentation_id:xxx, order:20});
 col.update({presentation_id:xxx, $and:[{order:{$lte:100}}, {order:{$gte:20}}]},{$inc:{order:-1}},{multi:true});
 col.update(moveSlide._id, {$set:{order:100}});