GridFS 的文件名字段(filename)存储在 fs.files 集合中,该集合专门保存文件元数据,而 fs.chunks 仅存二进制分块数据,不含 filename。

GridFS 的文件名字段在哪个集合里?
GridFS 实际把文件拆成两个集合:fs.files 存元数据(含 filename),fs.chunks 存二进制分块。你要模糊查文件名,必须查 fs.files,而不是直接对 GridFS API 调用 find —— 那些封装方法(比如 gridFSBucket.find())默认只返回游标,不支持原生聚合或正则,得手动切到集合层面。
在 fs.files 上用 $regex 的正确写法
MongoDB 的 $regex 支持字符串模式匹配,但要注意大小写和性能。直接在 filename 字段上查最稳妥:
db.fs.files.find({ filename: { $regex: "report.*2023", $options: "i" } })
-
$options: "i"表示忽略大小写,否则"Report"不会匹配"report" - 正则写在字符串里,不用
/.../包裹(那是 JavaScript shell 旧语法,驱动里不认) - 避免用
^开头的全匹配模式查大量文件,MongoDB 无法用索引加速前缀未知的正则(比如.*pdf) - 如果经常按文件名模糊查,建议给
filename加通配索引:db.fs.files.createIndex({ filename: "text" }),然后改用$text查询(但注意它不支持正则,只适合关键词搜索)
用 Node.js 驱动(如 mongodb@6+)执行正则查询的注意事项
新版驱动不接受字符串正则字面量,必须用 RegExp 对象或字符串形式的 $regex:
const filter = { filename: { $regex: "invoice_\d{4}-\d{2}", $options: "i" } };<br>const cursor = db.collection("fs.files").find(filter);
- 反斜杠要双写(
\d),否则 JS 字符串解析会吃掉一个 - 别用
new RegExp("...")传入,因为驱动可能序列化失败或丢失$options - 如果用
gridFSBucket.find()想套正则,行不通——它只接受简单对象过滤,不支持$regex。必须绕过 Bucket,直连fs.files集合 - 查到
_id后,再用bucket.findOne({ _id: fileId })获取文件流,不能省这步
为什么用 $regex 查 GridFS 文件名容易慢?
根本原因是 fs.files.filename 默认无索引,正则又没法走范围扫描。10 万文件以上,没索引的 $regex 查询可能秒级起步。
- 加普通单字段索引(
createIndex({ filename: 1 }))对$regex基本无效,除非正则以固定前缀开头(如^log_.*.txt)且开启了索引前缀优化(v5.0+) - 更现实的做法是:命名时带可检索结构,比如把年月放进文件名前缀(
2023-10-report.pdf),然后用{ filename: { $gte: "2023-10", $lt: "2023-11" } }配合索引快速定位 - 真正需要模糊语义(如“包含某词”“近似拼写”)的场景,得导出文件名建单独的搜索表,或接入 Elasticsearch
正则能跑通不等于该这么用;GridFS 本质不是为高频文本检索设计的,文件名只是元数据快照,别把它当全文字段使。











