如何对按非唯一字段排序的查询进行分页?例如,集合中的文档可能是(按s:1排序,然后是_id:-1):
import UIKit
var typingSpace = 80
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBOutlet weak var typingSpace: UIView!
@IBOutlet weak var displayLabel: UILabel!
}
有一个简单的限制/跳过方法可以......慢慢地工作。
是否可以使用以下内容:
{_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);
答案 0 :(得分:5)
如果您想通过"页码"进行分页。然后,在对密钥进行排序后,您几乎完全坚持使用.limit()
和.skip()
方法。你可能已经做了一些阅读,发现它并不是非常有效",主要是因为"跳过"通过" n"结果是为了达到某个页面。
但原则在你需要的地方是合理的:
db.collection.find().sort({ "s": -1, "_id": 1 }).skip(<page-1>).limit(<pageSize>)
如果您只需要移动&#34;前进&#34;在你的分页中,有一个更快的替代方法,也可以用于&#34;排序&#34;结果
关键是要保持对最后一次出现的&#34;&#34;价值&#34; s&#34;然后通常是_id
值的列表,直到&#34; s&#34;的值为止。变化。所以使用一些文档进行演示,这些文档已经过分类以便进行演示:
{ "_id": 1, "s": 3 },
{ "_id": 2, "s": 3 },
{ "_id": 3, "s": 3 },
{ "_id": 4, "s": 2 },
{ "_id": 5, "s": 1 },
{ "_id": 6, "s": 1 },
为了获得第一页&#34; &#34;两个&#34;结果您的第一个查询很简单:
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]
值。
这些东西你会存储在等待下一页请求的用户会话数据中。
根据您对下一页设置的请求,您可以按如下方式发出:
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
})
要求选择&#34; s&#34;需要从一个值&#34;小于或等于&#34; (由于排序的方向)记录了lastVal
,并且&#34; _id&#34;字段不能包含lastSeen
中记录的值。
生成的下一页是:
{ "_id": 3, "s": 3 },
{ "_id": 4, "s": 2 },
但现在如果您遵循逻辑,lastVal
当然是2
而lastSeen
现在只有单个数组元素[4]
。由于下一个查询只需要从2
继续作为一个较小或相等的值,因此不需要保留其他先前看过的&#34; _id&#34;因为它们不在该选择范围内。
然后这个过程紧随其后:
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
})
因此,通过遵循这种逻辑模式,您可以&#34;存储&#34;从您的&#34; previousc页面找到的信息&#34;结果和移动&#34;前进&#34;通过非常有效的结果。
但是如果你需要跳到&#34;第20页&#34;或类似的操作类型,然后您会遇到.limit()
和.skip()
。它的速度比较慢,但这取决于你能忍受的东西。
答案 1 :(得分:-2)
db.t1.drop()
db.t1.save({_id:19, s:3})
db.t1.save({_id:17, s:3})
db.t1.save({_id:58, s:4})
db.t1.find().sort({s:1, _id:-1}).skip(1).limit(2)
--Result
{ "_id" : 17, "s" : 3 }
{ "_id" : 58, "s" : 4 }
- $