gpt4 book ai didi

mongodb - 对集合进行排序和分页

转载 作者:可可西里 更新时间:2023-11-01 09:12:20 24 4
gpt4 key购买 nike

如何对按非唯一字段排序的查询进行分页?例如,集合中的文档可能是(按 s:1 排序,然后是 _id:-1):

{_id: 19, s: 3},
{_id: 17, s: 3},
{_id: 58, s: 4},
// etc...

有一个简单的限制/跳过方法可以工作......很慢。

是否可以使用类似的东西:

db.collection.find()
.sort({s:1, _id:-1})
.min({s:3, _id:17}) // this does not work as wanted!
.limit(2);

找回

{_id: 17, s: 3},
{_id: 58, s: 4}

?

最佳答案

如果您想按“页码”分页,那么您几乎只能使用 .limit().skip()对键的结果进行排序后应用的方法。您可能已经阅读了一些内容,发现它“效率不高”,主要是因为“跳过”“n”个结果以到达特定页面的成本。

但原则在您需要的地方是合理的:

db.collection.find().sort({ "s": -1, "_id": 1 }).skip(<page-1>).limit(<pageSize>)

如果您只需要在分页中“向前”移动,则可以使用更快的替代方法,也可以用于“排序”结果。

关键是保持对“s”的“最后一次看到”值的引用,然后通常是一个 _id 值列表,直到“s”的值发生变化。因此,使用更多文档进行演示,已经为演示目的进行了排序:

{ "_id": 1, "s": 3 },
{ "_id": 2, "s": 3 },
{ "_id": 3, "s": 3 },
{ "_id": 4, "s": 2 },
{ "_id": 5, "s": 1 },
{ "_id": 6, "s": 1 },

为了获得“两个”结果的“第一页”,您的第一个查询很简单:

db.collection.find().sort({ "s": -1, "_id": 1}).limit(2)

但是在处理文档时要遵循这一点:

var lastVal = null,
lastSeen = [];

db.collection.find().sort({ "s": -1, "_id": 1}).limit(2).forEach(function(doc) {
if ( doc.s != lastVal ) { // Change when different
lastVal = doc.s;
lastSeen = [];
}
lastSeen.push(doc._id); // Push _id onto array
// do other things like output
})

因此在第一次迭代中,lastVal 值将为 3 并且 lastSeen 将同时包含文档 _id数组 [1,2] 中的值。您可以将这些内容存储在诸如等待下一个页面请求的用户 session 数据之类的内容中。

根据您对下一页集的请求,您可以发出以下命令:

var lastVal = 3,
lastSeen = [1,2];

db.collection.find({
"_id": { "$nin": lastSeen },
"s": { "$lte": lastVal }
}).sort({ "s": -1, "_id": 1}).limit(2).forEach(function(doc) {
if ( doc.s != lastVal ) { // Change when different
lastVal = doc.s;
lastSeen = [];
}
lastSeen.push(doc._id); // Push _id onto array
// do other things like output
})

这要求“s”的选择需要从 lastVal 记录的“小于或等于”(因为排序方向)的值开始,并且“_id"字段不能包含记录在 lastSeen 中的值。

生成的下一页是:

{ "_id": 3, "s": 3 },
{ "_id": 4, "s": 2 },

但是现在,如果您遵循逻辑,lastVal 当然是 2lastSeen 现在只有单个数组元素 [4]。由于下一个查询只需要从 2 开始作为小于或等于的值,因此无需保留其他先前看到的“_id”值,因为它们不在该选择范围内。

然后流程继续:

var lastVal = 2,
lastSeen = [2];

db.collection.find({
"_id": { "$nin": lastSeen },
"s": { "$lte": lastVal }
}).sort({ "s": -1, "_id": 1}).limit(2).forEach(function(doc) {
if ( doc.s != lastVal ) { // Change when different
lastVal = doc.s;
lastSeen = [];
}
lastSeen.push(doc._id); // Push _id onto array
// do other things like output
})

因此,通过遵循该逻辑模式,您可以“存储”从结果的“前一页”中找到的信息,并非常有效地“向前”移动结果。

但是,如果您需要跳转到“第 20 页”或类似类型的操作,那么您将无法使用 .limit().skip()。那样比较慢,但这取决于您能忍受什么。

关于mongodb - 对集合进行排序和分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31163090/

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