MongoDB处理多个对象与订单字段



假设有一个包含许多幻灯片的演示文稿。mongo中的Presentation collection可以表示为: { _id: <presentation_id>, author: <author_name>, ... }

还有一个slides集合,其中包含了这些演示的幻灯片: { _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*/ }

就像所有的演示幻灯片一样,可以添加,移动,删除等,并且在每次操作后应该自动保存更改。在这种方案下,每次添加或移动幻灯片时,我们都需要更新许多幻灯片的顺序值。在meteor中,它会导致相当长的等待时间(例如,对于250张幻灯片的演示,如果我们在开头添加1张幻灯片,我们需要在for循环中更新250张现有幻灯片)。

我也想到了两件事如何处理这个问题:1)添加到presentation新字段slides,这将是一个数组,其中包含幻灯片id按顺序排列。但是这种方式有排序问题:目前mongodb不能通过id数组排序结果(在<=2.4版本中有一个使用$or的hack,但在2.6中它不再可用),而不使用聚合框架(它不存在于流星开箱即用,需要额外的模块)。这将用一个大更新取代大量的小更新。

2)另一种方法是将幻灯片集合中的order字段替换为两个新字段:prevnext,并仅保存下一个和上一个幻灯片id。这将减少(重新)移动/添加操作到几个小的更新,但是当我需要显示所有幻灯片时,我需要分两个步骤做到这一点:以不正确的顺序从数据库获取幻灯片,找到第一张(最后一张)幻灯片,并使用下一个/prev"链接"恢复正确的顺序。

选择哪种方式?或者可能有其他更好的方法来做这件事?

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

因为在幻灯片集合的几乎每个用例中,您都需要来自演示集合的数据。数组总是有序的,所以你不应该需要/要求幻灯片的_id字段。

唯一的限制是整个演示文档不能超过16mb。

你可以使用mongodb的数组更新修饰符在集合中移动幻灯片。$position修饰符对于添加特别有用。你可以组合$splice和$push来移动东西。

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

在顺序中间插入幻灯片:

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

这将从20开始增加所有的order字段,因此实际上释放了位置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}});

相关内容

最新更新