2011-04-02 31 views
17

我可能错过了一些东西,因为我仍然在学习MongoDB的入口和 ,但我需要分页收集帮助。如何在MongoDB中使用范围查询进行分页?

我有一个集合,它有一个名称列表。

牛肉
鸡胸的底部圆6盎司
鸡胸8盎司
鸡胸8盎司
鸡胸8盎司
鸡胸随机
鸡腿
鸡里脊肉
鸡大腿
粗盐

我在“ProductName,_id”上创建了一个复合索引。

我运行此查询:

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

公告有3个 “鸡胸8盎司” 项目。

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

如果我是寻呼和从顶部开始。该查询将错过 其他2“鸡胸8盎司”。

所以,如果每个页面只能有3个项目,我希望看到第2页,然后我看到..
鸡胸8盎司
鸡胸8盎司
鸡胸随机。

但我不是。这是去年的鸡胸肉8盎司,而是从那里开始。

有没有办法解决这个问题?
如果列表按相反方式排序,我该如何做?

+1

你是什么要求采取?三个返回的行非常好,与您的查询匹配,或者您期望什么,为什么? – 2011-04-02 19:26:52

+0

首先放松一下。很显然,我没有正确解释这一点。如果每个页面只能有3个项目,我想看第2页,那么我应该看到鸡胸肉8盎司,鸡胸肉8盎司,鸡胸肉随机。但我不是。它的最后鸡胸8盎司,并从那里开始。 – 2011-04-02 19:32:15

+0

因为我做错了我将如何获得第2页与我列出的项目? – 2011-04-02 19:38:24

回答

27

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

创建合成指数

db.ProductGuideItem.ensureIndex({ ProductName:1, _id:1}); 

这解决了我的问题。
参考: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} 

所以,你的一系列基于分页做到这一点(第2页大小):

第一页

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

第2页

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

{a:2, b:2} 
{a:2, b:3} 

第3页

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

这里是$最小/最大文档: http://www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers

如果没有您的收藏中重复的值,您不需要使用最大值或创建复合索引。您可以使用$ lt & $ gt。

+0

我认为这是一个有趣而有用的视角,用于非独特领域的基于范围的分页。但是,如果_id字段是查询的一部分,我认为您的复合索引不是很有用。原因是_id字段是唯一的,并且它将自动能够使用默认的_id索引而不是复合索引。看到这里的推理http://stackoverflow.com/questions/9598633/mongodb-unique-index-vs-compound-index – 2012-06-26 14:16:09

+0

当使用这种方法,你需要强制mongodb使用索引'{ProductName:1,_id: 1}“如果你不知道你的结果会失灵。 – 2012-06-27 14:18:02

+0

这不适用于您向用户显示分页组件(例如,“页面1,页面2,页面3,...,页面10)”的分页,因为您无法随意点击“Page#N”链接,因为要工作,首先你需要最后一个'ObjectID'作为'Page#N-1'。 这适用于Google+,Facebook或Twitter等“无限滚动”页面。 – Behrang 2014-02-09 12:05:46

5

你只需要调用跳过光标

看到cursor skip MongoDB的文档“这种方法可以对实现有用的‘分页’结果”。

这个例子是从MongoDB的example

function printStudents(pageNumber, nPerPage) { 
    print("Page: " + pageNumber); 
    db.students.find().skip((pageNumber-1)*nPerPage).limit(nPerPage).forEach(function(student) { print(student.name + "<p>"); }); 
} 
相关问题