MongoDB的分頁查詢就需要先對數據進行一個排序,數據量過大的時候我們排序就會報錯誤。
error: "Internal Server Error",…}error: "Internal Server Error"
message: "Query failed with error code 96 and error message 'Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.' on server localhost:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 96 and error message 'Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM.
這個問題根據提示及網上找資料就是兩種解決方案。一種爲增加內存;一種就是創建索引的方式。
我們先來說第一種,mongodb的sort操作是把數據拿到內存中再進行排序的,爲了節約內存,默認給sort操作限制了最大內存爲32Mb,當數據量越來越大直到超過32Mb的時候就自然拋出異常了。因爲項目着急使用及演示,我先用的第一種我直接將內存增加10倍320MB,當時確實解決了,但是數據不斷增多,又提示該異常了。這個解決方案不怎麼友好啊。
項目演示完成之後,我就決定將拋棄第一種方式,使用第二種方式,使用第二種方式其實還有一個好處下面我會講到。
增加索引
db.yourCollection.createIndex({<field>:<1 or -1>})
具體要對哪個字段加索引,可根據需求自己定義,其中1表示升序排列,-1表示降序排列。索引創建之後即時生效,不需要重啓數據庫和服務器程序,也不需要對原來的數據庫查詢語句進行修改。
這樣我們先解決了排序導致的系統問題。
有序的排序,進行常規的分頁操作,
我做了三種方式
第一種直接使用skip及limit
根據傳來的page 及 pageSzie 來進行判斷
當page=1 作爲第一頁面時,我們不需要skip 這裏注意需要單獨的一個校驗,skip(0)會提示錯誤
query.limit(pageSize);
if (page == 1) {
} else {
page = page - 1;
int skip = page * pageSize;
query.skip(skip);
}
第二種直接使用limit
這個也需要對page=1時,進行校驗
實現原理就是先查出上頁的最後一條的ID 用這個ID來做爲查詢我們想要頁面的查詢條件
if (page == 1) {
query.limit(pageSize);
} else {
//查看上頁最後一條數據的所在位置
int number = (page - 1) * limit;
query.limit(number);
//根據這個條件先查詢出所有的結果
//根據這個頁面拿出最後結果的ID
。。。。。。。。。。。。。。。。。。這個代碼就先不寫了。。。。。。
// 拿出ID 使用lt 來查詢 這樣查出的結果就是這個ID之後的數據了,從而實現分頁
query.addCriteria(Criteria.where("_id").lt(id));
query.limit(pageSize);//這裏注意要重新賦值
}
第二種直接使用limit
這個也需要對page=1時,進行校驗
實現原理就是先查出所有的條數,根據條數及page我們能查出想要頁面的數據條數區間