Javascript 在mongodb中实现分页

Javascript 在mongodb中实现分页,javascript,mongodb,pagination,mongodb-query,Javascript,Mongodb,Pagination,Mongodb Query,我知道使用skip来实现分页是一种不好的做法,因为当数据变大时skip开始消耗大量内存。克服此问题的一种方法是按\u id字段使用自然顺序: //Page 1 db.users.find().limit(pageSize); //Find the id of the last document in this page last_id = ... //Page 2 users = db.users.find({'_id'> last_id}). limit(10); 问题是-我是mon

我知道使用
skip
来实现分页是一种不好的做法,因为当数据变大时
skip
开始消耗大量内存。克服此问题的一种方法是按
\u id
字段使用自然顺序:

//Page 1
db.users.find().limit(pageSize);
//Find the id of the last document in this page
last_id = ...

//Page 2
users = db.users.find({'_id'> last_id}). limit(10);

问题是-我是mongo的新手,不知道获得这个最后一个id的最佳方法是什么。您所谈论的概念可以称为“前向分页”。这样做的一个很好的原因与使用
.skip()
.limit()
修饰符不同,这不能用于“返回”到上一页,也不能用于“跳过”到特定页。至少不需要花费大量精力来存储“看到的”或“发现的”页面,因此,如果您需要这种类型的“页面链接”页面,那么最好还是坚持使用
.skip()
.limit()
方法,尽管存在性能缺陷

如果只“前进”对您来说是一个可行的选择,那么以下是基本概念:

db.junk.find().limit(3)
{“_id”:ObjectId(“54c03f0c2f63310180151877”),“a”:1,“b”:1}
{“_id”:ObjectId(“54c03f0c2f63310180151878”),“a”:4,“b”:4}
{u id:ObjectId(“54c03f0c2f63310180151879”),“a:10,“b:10}
当然,这是您的第一页,限制为3项。现在考虑用代码迭代光标:

var lastSeen=null;
var cursor=db.junk.find().limit(3);
while(cursor.hasNext()){
var doc=cursor.next();
printjson(doc);
如果(!cursor.hasNext())
lastSeen=doc.\u id;
}
因此,它会迭代光标并执行某些操作,当到达光标中的最后一项时,您会将
lastSeen
值存储到当前
\u id

ObjectId(“54c03f0c2f63310180151879”)
在随后的迭代中,您只需将保留的
\u id
值(在会话或其他任何情况下)输入查询:

var cursor=db.junk.find({“\u id”:{“$gt”:lastSeen}).limit(3);
while(cursor.hasNext()){
var doc=cursor.next();
printjson(doc);
如果(!cursor.hasNext())
lastSeen=doc.\u id;
}
{“_id”:ObjectId(“54c03f0c2f6331018015187a”),“a”:1,“b”:1}
{“_id”:ObjectId(“54c03f0c2f6331018015187b”),“a”:6,“b”:6}
{“_id”:ObjectId(“54c03f0c2f6331018015187c”),“a”:7,“b”:7}
这个过程反复重复,直到不能得到更多的结果

这是自然顺序的基本过程,例如
\u id
。对于其他一些事情,它变得更复杂一些。考虑以下事项:

{u id:4,“rank:3}
{u id:8,“rank:3}
{u id:1,“rank:3}
{u id:3,“rank:2}
若要将其分为两个按排名排序的页面,则您基本上需要知道的是您“已经看到”的内容,并排除这些结果。看第一页:

var lastSeen=null;
var seenIds=[];
var cursor=db.junk.find().sort({“rank”:-1}).limit(2);
while(cursor.hasNext()){
var doc=cursor.next();
printjson(doc);
if(lastSeen!=null&&doc.rank!=lastSeen)
seenIds=[];
seenIds.push(doc.\u id);
如果(!cursor.hasNext()| | lastSeen==null)
lastSeen=doc.rank;
}
{u id:4,“rank:3}
{u id:8,“rank:3}
在下一次迭代中,您希望小于或等于上次看到的“排名”分数,但也不包括那些已经看到的文档。您可以使用操作员执行此操作:

var cursor=db.junk.find(
{“_id”:{“$nin”:seenIds},“rank”:“$lte”:lastSeen}
).sort({“rank”:-1}).limit(2);
while(cursor.hasNext()){
var doc=cursor.next();
printjson(doc);
if(lastSeen!=null&&doc.rank!=lastSeen)
seenIds=[];
seenIds.push(doc.\u id);
如果(!cursor.hasNext()| | lastSeen==null)
lastSeen=doc.rank;
}
{u id:1,“rank:3}
{u id:3,“rank:2}
您实际持有的“seenid”数量取决于您的结果的“粒度”,即该值可能发生变化的地方。在这种情况下,您可以检查当前的“排名”分数是否不等于
lastSeen
值,并丢弃当前的
seenIds
内容,使其不会增长太多


这是“前向分页”的基本概念,供您练习和学习。

谢谢!但是我不知道我应该如何得到最后一个id。我应该用什么代码来代替这些点:
last\u id=…
?@Neil Lunn,这是一个完整而漂亮的解释。我发现了一些关于你的事情,似乎你从不睡觉,我监视你(开玩笑),看到你总是24/7在线;)@Disposer移动应用程序和机器人。机器的崛起。