Mongodb 使用Mongoose跳过大量记录时如何避免内存限制?
在拥有超过10万条记录的集合上,当我使用Mongoose选项进行查询时,如下所示:Mongodb 使用Mongoose跳过大量记录时如何避免内存限制?,mongodb,indexing,mongoose,Mongodb,Indexing,Mongoose,在拥有超过10万条记录的集合上,当我使用Mongoose选项进行查询时,如下所示: contact.find({}, {}, { collation: { locale: 'en_US', strength: 1 }, skip: 90000, limit: 10, sort: { email: 1 } }); 我得到这个错误: MongoError:find期间执行器错误命令:OperationFailed:排序操作使用的RAM超过最大3355
contact.find({}, {}, {
collation: {
locale: 'en_US',
strength: 1
},
skip: 90000,
limit: 10,
sort: {
email: 1
}
});
我得到这个错误:
MongoError:find期间执行器错误命令: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)
您所经历的是由于
跳过。正如你在书中看到的
cursor.skip()方法通常代价高昂,因为它要求服务器在开始返回结果之前,从集合或索引的开头开始遍历以获取偏移量或跳过位置。随着偏移量(例如上面的页码)的增加,cursor.skip()将变得更慢,CPU消耗也更大。对于较大的集合,cursor.skip()可能会被IO绑定
你应该找到一个更好的方法,而不是跳过。当您使用电子邮件
字段对文档进行排序时,您可以使用电子邮件字段编写一个范围查询,而不是像这样编写跳过
:
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页。因此,在查询中,您只能跳过50-60个文档,并结合电子邮件
字段中的$gt
和$lt
另一种方法是使用其他一些工具在内存中缓存数据
我想你明白了。快乐编码。如果您将电子邮件(指示排序顺序的字段)添加为@Jankapunkt,email
…FWIW上已经有一个索引,您可以增加MongoDB用于排序操作的内存量:如果您的解决方案有效,那么它对我们的无状态Rest API不起作用。如果用户使用查询参数?page=790将第790页添加为书签,则必须逐页获取到第790页才能获得最终结果,这似乎是错误的。@MaximeSelin建议的解决方案(尽管有点缺陷,因为它仍然包含一个skip
,不应该再存在了)是MongoDB自己建议使用的地址:记住上一页的最后一个电子邮件地址,并使用该地址执行范围查询。@robertklep我从question复制了查询,但忘记删除跳过部分,tnx以提醒。@barbakini感谢您的时间,Mongo给出的错误消息让我感到困惑。有没有关于它为什么在Mongo shell中工作的解释?可能使用具有该shell语法的聚合?