2011-12-05 43 views
7

我需要分页收集文章(按日期排序 - 除此之外别无其他)。在Mongodb中做这样的标准方式是什么?如何在Mongodb中实现分页?

由于性能问题,我不打算使用skip()方法。我也不打算使用$ push方法。我所见过的最接近的方法是范围查询方法。但是,如果任何已排序的项目被删除,它似乎会失败。

+2

接受答案并关闭此问题 – beNerd

回答

9

范围排序应该适合你。首先要求将前10个项目按日期排序:

db.articles.find({}).sort({ date : -1 }).limit(10); 

这之后,您将需要储存的最后一个项目的某个日期,并在接下来的寻呼请求使用ID:

db.articles.find({"date": {$lt: storedDateOfLastItem}}).sort({ date : -1 }).limit(10); 

所以,我想它应该为你工作。要估算总页数,您需要使用count

但它似乎失败,如果任何排序项目被删除。

如果您将从第#1页移除文章,确保因存储上次日期而中断第2页将被更改。为了避免如果这个数被改变,这是目前保存日期

db.articles.find({"date": {$gt: storedDateOfLastItem}}).sort({ date : -1 }).count() 

之前的项目这一点,你可以估算数(让说,2 articled被删除)。您需要更新storedDateOfLastItem

db.articles.find({"date": {$gt: storedDateOfLastItem}}).sort({ date : -1 }).take(2) 

再从上述请求的最后一个项目采取storedDateOfLastItem并继续使分页。

但我的意见只是保持这种分页,因为它是没有额外的逻辑,因为我想删除文章是罕见的操作。

从MongoDB的文档:

寻呼成本不幸的是跳过即可(非常)昂贵,需要 服务器从集合,或索引的开始行走,让 为偏置/跳过位置才能开始返回 数据页(限制)。随着页面号增加,跳过将变得更慢,并且更多的CPU密集,并且可能IO限制,更大的集合。

基于范围的分页可以更好地使用索引,但不允许 您可以轻松地跳转到特定页面。

+0

使用日期类型的范围查询/页面标记不起作用,因为您将得到具有相同日期的多个记录的不一致性。我会为此使用_id值标记。所有这些都是为了避免跳跃(N)时的o(N)表现。 –

+0

啊hhhh在mongodb中调页很繁琐吗?我希望10gen的人向我们展示他们如何推荐分页。 –

+0

@LulZilla:看看我的更新,它来自mongodb文档。 –

0

如果您可以对索引进行排序,则可以使用“$ min”和“$ max”查询修饰符或范围查询来实现高效的分页。确保您的索引最后包含一个独特的属性(例如“_id”)。

如果您无法对索引进行排序,则可以预处理完整的结果集并按顺序保留“_id”值的列表。然后,您可以使用“$ in”查询运算符获取该列表的范围并查找结果页面。