在具有超过100k记录的集合上,当我使用Mongoose选项查询时:
contact.find({}, {}, {
collation: {
locale: 'en_US',
strength: 1
},
skip: 90000,
limit: 10,
sort: {
email: 1
}
});
我收到此错误:
MongoError:查找命令期间执行程序错误:OperationFailed:排序操作使用的RAM超过最大33554432字节。添加索引,或指定较小的限制。
但我确实在电子邮件字段中有索引:
{
"v" : 2,
"key" : {
"email" : 1
},
"name" : "email_1",
"ns" : "leadfox.contact",
"background" : true
}
另一方面,当我在Mongo shell中查询时,它工作正常:
db.contact.find().sort({email: 1}).skip(90000).limit(10)
答案 0 :(得分:1)
您遇到的是skip
。正如您在documentation
cursor.skip()方法通常很昂贵,因为它要求服务器从集合或索引的开头走,以在开始返回结果之前获取偏移或跳过位置。随着偏移量(例如上面的pageNumber)的增加,cursor.skip()将变得更慢并且CPU密集度更高。对于较大的集合,cursor.skip()可能会成为IO绑定。
你应该找到一个更好的方法而不是跳过。当您使用email
字段对文档进行排序时,您可以使用电子邮件字段而不是skip
编写范围查询:
contact.find({ "email": { $gt: the_last_email_from_previous_query } }, {}, {
collation: {
locale: 'en_US',
strength: 1
},
limit: 10,
sort: {
email: 1
}
});
更新:
首先。就像我上面说的那样,你想要的是不可能的。 Mongodb说,而不是我。
其次,我建议您搜索现代分页方法和人们使用案例。你在评论中的例子是荒谬的。对于任何数据,没有用户应该/将直接转到第790页。如果他们直接进入这样的页面,很可能意味着,他们将数据覆盖到第790页并且他们想要继续。因此,即使您正在构建无状态系统(如同所有现代系统一样),您应该存储有关用户最终点视图的一些信息,以用于分页数据。这是一个基于用户行为的示例方法(我不是说最好,它只是一个例子)。
另一种方法,您可以使用(像大多数现代分页表一样),您只允许用户向前或向后导航5-6页。因此,您只能在$gt
字段中与$lt
和email
一起跳过查询中的50-60文档。
另一种方法可以是使用其他一些工具在内存中缓存数据。
我想你得到的照片。快乐的编码。