所以我用 mongoose 运行一个 Node.js 服务器,我一直在尝试使用 GridFS node 包下载一个大的 file 但我收到以下错误:
MongoServerError: 执行器错误在 find 命令 :: 中导致 :: Sort 超出了 104857600 字节的内存限制,但没有选择外部排序。
这是我用来下载 file 的代码:
// Stream a single file.
router.get('/stream/:filename', async function(req, res, next){
try{
const file = gfs.find({
filename: req.params.filename
}).toArray((err, files) => {
if (!files || files.length === 0) {
return res.status(404)
.json({
err: "no files exist"
});
}
gfs.openDownloadStreamByName(req.params.filename)
.pipe(res);
});
}catch(err){
return res.status(400).json({
err:'Could not fetch the file.'
})
}
});
鉴于https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/,我想记录这个问题,以便我的解决方案可以帮助其他人以后遇到它。
回答1
事实证明,当您通过使用 GridFS 流式下载 file 时,构成 file 的文档会被排序。根据 https://developerslogblog.wordpress.com/2019/11/27/mongodb-sort-how-to-fix-maximum-ram-exceeded-error/,在进行排序时,MongoDB 首先尝试使用索引中指定的顺序检索文档。当没有可用的索引时,它会尝试将文档加载到内存中并在那里对其进行排序。
问题是 Mongo 默认配置为在超过 32 MB 的使用量时中止操作。这就是我们遇到上述“排序超出内存限制”错误的原因。为了解决这个问题,您必须为包含要下载的 file 块的顺序的“n”字段创建一个索引。为此,您可以直接通过数据库界面创建索引(我使用 MongoDB Compass GUI),也可以使用 createIndex() 方法通过代码创建它:
// Create an index for the 'n' field to help sort the chunks collection.
db.collection('files.chunks').createIndex({n: 1});