如何在MongoDB中使用范围查询进行分页?

Don*_* V. 19 pagination mongodb

我可能会遗漏一些东西,因为我还在学习MongoDB的细节,但我需要帮助分页集合.

我有一个有名单的集合.

底部牛肉
鸡胸肉6oz鸡胸肉
8oz
鸡胸肉8oz
鸡胸肉8oz
鸡胸肉随机
鸡腿
鸡里脊
肉鸡大腿
犹太盐

我在"ProductName,_id"上创建了一个复合索引.

我运行这个查询:

db.ProductGuideItem.find( { ProductName: { $gt: "Chicken Breast 8oz" } } ).sort({ProductName:1,_id:1}).limit(3); 
Run Code Online (Sandbox Code Playgroud)

请注意,有3个"鸡胸肉8oz"项目.

如果我运行该查询,我得到...
鸡胸肉随机
鸡腿
鸡里脊肉

如果我正在分页并从顶部开始.该查询将错过其他2"鸡胸肉8oz".

因此,如果每个页面只能有3个项目,我想看到第2页,那么我应该看到..
鸡胸肉8oz
鸡胸肉8oz
鸡胸肉随机.

但我不是.这将是最后一个鸡胸肉8盎司,并从那里开始.

有没有解决的办法?
如果列表以相反的方式排序,我该怎么做呢?

Don*_* V. 29

由于我正在分页的集合有重复的值,我必须在ProductName和id上创建一个复合索引.

创建复合索引

db.ProductGuideItem.ensureIndex({ ProductName:1, _id:1});
Run Code Online (Sandbox Code Playgroud)

这解决了我的问题.
参考:https://groups.google.com/d/msg/mongodb-user/3EZZIRJzW_A/oYH79npKZHkJ

假设你有这些值:

{a:1, b:1}
{a:2, b:1}
{a:2, b:2}
{a:2, b:3}
{a:3, b:1}
Run Code Online (Sandbox Code Playgroud)

所以你为基于范围的分页(页面大小为2)执行此操作:

第1页

find().sort({a:1, b:1}).limit(2)
{a:1, b:1}
{a:2, b:1}
Run Code Online (Sandbox Code Playgroud)

第2页

find().min({a:2, b:1}).sort({a:1, b:1}).skip(1).limit(2)

{a:2, b:2}
{a:2, b:3}
Run Code Online (Sandbox Code Playgroud)

第3页

find().min({a:2, b:3}).sort({a:1, b:1}).skip(1).limit(2)
{a:3, b:1}
Run Code Online (Sandbox Code Playgroud)

以下是$ min/max的文档:http: //www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers

如果集合中没有重复值,则无需使用min和max或创建复合索引.你可以使用$ lt&$ gt.

  • 这不适合向用户显示分页组件(例如“第 1 页,第 2 页,第 3 页,...,第 10 页”)的分页,因为您不能随机单击“第 #N 页”链接,因为要使其工作,首先您需要“Page #N-1”的最后一个“ObjectID”。这更适合“无限滚动”页面,例如 Google+、Facebook 或 Twitter。 (2认同)

mos*_*eri 12

你只需要在光标上调用skip

请参阅关于游标的 MongoDB文档"这种方法在实现"分页"结果时可能很有用".

这个例子来自Mongodb的例子

function printStudents(pageNumber, nPerPage) {
   print("Page: " + pageNumber);
   db.students.find().skip((pageNumber-1)*nPerPage).limit(nPerPage).forEach( function(student) { print(student.name + "<p>"); } );
}
Run Code Online (Sandbox Code Playgroud)

  • 不确定这是否是正确的方法,因为作者声称使用跳过会减慢速度。https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-1 (2认同)

Aka*_*mar 6

下面的代码将从第一页返回 10 个文档,其余页面也类似。

const perPage = 10 //10docs in single page
const page = 1 //1st page
db.collection.find({}).skip(perPage * page).limit(perPage)
Run Code Online (Sandbox Code Playgroud)