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我们能查出想要页面的数据条数区间