GridFS Large File Download Crashes the Node.js Server. MongoServerError: Sort exceeded memory limit of bytes

GridFS Large File Download Crashes the Node.js Server. MongoServerError: Sort exceeded memory limit of bytes

所以我是 运行 一个带有 mongoose 的 Node.js 服务器,我一直在尝试 使用 GridFS 节点包 下载一个大文件但是我收到以下错误:

MongoServerError: Executor error during find command :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting.

这是我用来下载文件的代码:

// 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.'
        })
    }
}); 

考虑到 it's OK to answer your own question on Whosebug,我想记录这个问题,以便我的解决方案可以帮助以后遇到它的其他人。

事实证明,当您通过使用 GridFS 流式传输文件来下载文件时,组成该文件的文档会被排序。根据 this blog post,在进行排序时,MongoDB 首先尝试使用索引 中指定的顺序检索文档。当没有索引可用时,它将尝试将文档加载到内存中并在那里对它们进行排序。

要注意的是 Mongo 默认配置为在超过 32 MB 的使用量时中止操作。这就是我们 运行 进入上述“排序超出内存限制”错误的原因。为了解决这个问题,你必须为包含你要下载的文件块顺序的“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});