2011-04-02 64 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>"); }); 
} 
相關問題