gpt4 book ai didi

javascript - 在 mongodb 中实现分页

转载 作者:可可西里 更新时间:2023-11-01 10:49:03 26 4
gpt4 key购买 nike

我知道使用 skip 来实现分页是一种不好的做法,因为当你的数据变大时 skip 开始消耗大量内存。解决这个问题的一种方法是使用 _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 的新手,不知道什么是获得这个 last_id

的最佳方法

最佳答案

你说的这个概念可以叫做“前向分页”。一个很好的理由与使用 .skip().limit() 修饰符不同,这不能用于“返回”到上一页或实际上“跳过”到特定页面。至少不需要花费大量精力来存储“已看到”或“已发现”页面,因此如果您想要这种类型的“页面链接”分页,那么您最好坚持使用 .skip( ).limit() 方法,尽管存在性能缺陷。

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

db.junk.find().limit(3)

{ "_id" : ObjectId("54c03f0c2f63310180151877"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("54c03f0c2f63310180151878"), "a" : 4, "b" : 4 }
{ "_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);
if (!cursor.hasNext())
lastSeen = doc._id;
}

因此迭代游标并做一些事情,当到达游标中的最后一项为真时,您将 lastSeen 值存储到当前 _id:

ObjectId("54c03f0c2f63310180151879")

在您的后续迭代中,您只需将您保留(在 session 中或其他任何内容中)的 _id 值提供给查询:

var cursor = db.junk.find({ "_id": { "$gt": lastSeen } }).limit(3);

while (cursor.hasNext()) {
var doc = cursor.next();
printjson(doc);
if (!cursor.hasNext())
lastSeen = doc._id;
}

{ "_id" : ObjectId("54c03f0c2f6331018015187a"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("54c03f0c2f6331018015187b"), "a" : 6, "b" : 6 }
{ "_id" : ObjectId("54c03f0c2f6331018015187c"), "a" : 7, "b" : 7 }

这个过程不断重复,直到再也得不到结果。

这是_id 等自然顺序的基本过程。对于其他事情,它会变得有点复杂。请考虑以下事项:

{ "_id": 4, "rank": 3 }
{ "_id": 8, "rank": 3 }
{ "_id": 1, "rank": 3 }
{ "_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._id);
if (!cursor.hasNext() || lastSeen == null)
lastSeen = doc.rank;
}

{ "_id": 4, "rank": 3 }
{ "_id": 8, "rank": 3 }

在下一次迭代中,您希望小于或等于 lastSeen“排名”分数,但也排除那些已经看到的文档。您使用 $nin 执行此操作运算符(operator):

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._id);
if (!cursor.hasNext() || lastSeen == null)
lastSeen = doc.rank;
}

{ "_id": 1, "rank": 3 }
{ "_id": 3, "rank": 2 }

您实际持有多少“seenId”取决于您的结果在该值可能发生变化时的“粒度”程度。在这种情况下,您可以检查当前的“排名”分数是否不等于 lastSeen 值并丢弃当前的 seenIds 内容,使其不会增长太多。

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

关于javascript - 在 mongodb 中实现分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45213171/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com