MongoDB的管理操作中,列出数据库是一项高频需求。大多数开发者第一时间想到的是show dbs这个shell命令,或者调用listDatabases管理命令。但很少有人知道,从MongoDB 4.4开始,聚合管道也提供了一个专门的管理阶段——$listDatabases,它把数据库列表查询直接纳入了聚合框架的体系,可以和$match、$project等阶段无缝衔接,实现传统命令做不到的灵活过滤能力。本文将围绕这个阶段的语法、用法和注意事项展开详细讲解。

$listDatabases的基本语法与返回结构
$listDatabases必须作为聚合管道的第一个阶段使用,这一点和$currentOp等管理类阶段类似。它的基本写法有两种,一种是不带任何参数直接使用,另一种是传入一个文档指定选项。直接使用时,MongoDB会返回实例上所有数据库的信息,返回结果是一个名为databases的数组,每个元素对应一个数据库。
不带参数的调用方式如下:
use admin
db.aggregate([
{ $listDatabases: 1 }
])
返回的文档结构大致是这样的:顶层只有一个databases字段,它是一个数组,数组中的每个元素包含name(数据库名)、sizeOnDisk(磁盘占用字节数)和empty(是否为空库)三个字段。如果传入了nameOnly: true选项,则只返回name字段,可以有效减少返回数据量。需要注意,这个聚合操作必须在admin数据库上执行,否则会报错。
带选项的完整语法如下:
use admin
db.aggregate([
{
$listDatabases: {
nameOnly: true,
filter: {
name: { $regex: /^report/ }
}
}
}
])
其中filter选项允许在服务器端过滤数据库列表,比如只返回名字以report开头的库,authorizedDatabases: true则表示只返回当前用户有权限查看的数据库。这些选项和listDatabases命令中的参数是一致的。
与其他管道阶段组合实现灵活查询
$listDatabases最大的价值在于它可以和后续的聚合阶段组合。传统的listDatabases命令返回结果后,如果想在客户端做进一步处理,需要自己写脚本解析。而在聚合管道中,直接接上$unwind把databases数组展开,再用$sort、$match、$limit等阶段处理,一行流水线就能完成。
下面的例子先列出所有数据库,然后展开数组、过滤掉空库,最后按磁盘占用从大到小排序:
use admin
db.aggregate([
{ $listDatabases: {} },
{ $unwind: "$databases" },
{ $replaceRoot: { newRoot: "$databases" } },
{ $match: { empty: false } },
{ $sort: { sizeOnDisk: -1 } },
{ $project: { _id: 0, name: 1, sizeOnDisk: 1 } }
])
这段管道的执行逻辑是:先用$listDatabases拿到原始结果,此时结果只有一个文档,databases字段是数组;接着$unwind把数组拆成多个文档;$replaceRoot把每个文档的根提升为数组元素本身,这样后续阶段就可以直接引用name和sizeOnDisk字段;最后完成过滤、排序和字段裁剪。这种写法在运维监控脚本里非常实用,比如找出占用磁盘最多的前几个数据库。
再举一个配合正则匹配的例子,统计所有业务库名中包含log的数据库数量:
use admin
db.aggregate([
{ $listDatabases: { nameOnly: true } },
{ $unwind: "$databases" },
{ $match: { "databases.name": /log/i } },
{ $count: "logDbCount" }
])
值得注意的是,filter选项和管道中的$match虽然都能过滤,但filter是在服务器端提前过滤,减少了数据传输量,性能更好;$match则更灵活,支持完整的查询操作符。实际使用时建议优先用filter做粗筛,再用$match做精筛。
与show dbs和listDatabases命令的区别及注意事项
三种方式各有适用场景。show dbs是mongosh的辅助方法,底层仍然是执行listDatabases命令,只适合交互式查看,无法参与程序化处理。db.adminCommand({ listDatabases: 1 })是管理命令,返回结果需要客户端自己解析。而$listDatabases是聚合阶段,天然支持管道组合,是最适合写进应用程序和监控脚本的方式。三者的对比可以总结为下表:
| 方式 | 类型 | 能否管道组合 | 返回内容可定制性 |
|---|---|---|---|
| show dbs | shell辅助方法 | 否 | 低 |
| listDatabases命令 | 管理命令 | 否 | 中(支持filter) |
| $listDatabases阶段 | 聚合阶段 | 是 | 高(配合所有管道阶段) |
使用时还有几个容易踩坑的地方需要留意。第一,版本要求。$listDatabases是MongoDB 4.4才引入的阶段,如果你的集群版本低于4.4,执行时会直接报错,这一点在升级改造老项目时尤其要确认。第二,权限要求。执行者需要具备列出数据库的权限,普通用户可能只能看到部分数据库,或者收到权限错误,此时可以配合authorizedDatabases: true只返回有权查看的库。第三,它只能用于独立聚合,不能出现在$lookup的子管道或者$unionWith的子管道中,因为它必须在管道的起始位置。
另外提一个实战细节:在分片集群环境下,$listDatabases返回的sizeOnDisk是各分片数据的汇总估算值,可能与实际磁盘占用存在轻微偏差。如果需要精确监控存储,建议结合$collStats和$dbStats等聚合阶段一起使用,构建完整的存储监控管道。
总结一下,$listDatabases把数据库级别的管理查询带进了聚合框架,配合$unwind、$match、$sort等阶段可以轻松实现各种定制化的数据库列表查询。对于需要在应用代码中动态感知数据库结构的场景,比如多租户系统、数据归档工具、存储监控平台,它都比传统命令更加优雅和强大。
MongoDBMongoDB聚合管道$listDatabases修改时间:2026-09-06 03:44:29