我在MongoDB中拥有一个包含15万多个文档的集合。我在Node.js中为MongoDB使用Mongoose ODM v5.4.2。在数据检索时,我正在使用带有$ skip和$ limit的聚合查找进行分页。我的代码运行正常,但是在100k文档之后,需要10-15秒才能检索到数据。但是在$ skip和$ limit的帮助下,我一次只显示100条记录。我已经为foreignField创建了索引。但它仍在变慢。
campaignTransactionsModel.aggregate([{
$match: {
campaignId: new importModule.objectId(campaignData._id)
}
},
{
$lookup: {
from: userDB,
localField: "userId",
foreignField: "_id",
as: "user"
},
},
{
$lookup: {
from: 'campaignterminalmodels',
localField: "terminalId",
foreignField: "_id",
as: "terminal"
},
},
{
'$facet': {
edges: [{
$sort: {
[sortBy]: order
}
},
{ $skip: skipValue },
{ $limit: viewBy },
]
}
}
]).allowDiskUse(true).exec(function(err, docs) {
console.log(docs);
});
答案 0 :(得分:1)
查询花费的时间更长,因为服务器从输入结果的开头(在跳过阶段之前)开始扫描以跳过给定数量的文档并设置新结果。
来自MongoDB官方文档:
cursor.skip()方法要求服务器从 开始返回结果之前输入结果集的开始。 随着偏移量的增加,cursor.skip()会变慢。
您可以使用range
个查询来模拟与.skip()
或skip stage(aggregation)
相似的结果
使用范围查询
范围查询可以使用索引来避免扫描不需要的文档, 与偏移相比,随着偏移的增加,通常会产生更好的性能 使用cursor.skip()进行分页。
降序
使用此过程来实现范围查询的分页:
- 选择诸如_id之类的字段,该字段通常会以一致的方式更改 随时间变化的方向,并具有唯一索引以防止重复 值
- 查询字段小于起始值的文档 使用
$lt
和cursor.sort()
运算符,以及- 存储下一个查询的上次看到的字段值。
订单递增 -查询其字段小于起始值的文档 使用
$gt
和cursor.sort()
运算符,以及
假设您获得的最后一个文档具有_id:objectid1,那么您可以查询具有_id : {$lt : objectid1}
的文档,以降序获取文档。对于递增顺序,您可以查询具有_id : {$gt : objectid1}
阅读Range queries上的官方文档以了解更多信息。