$unionWith 是聚合阶段,必须置于 db.collection.aggregate() 管道中使用,不可在顶层直接调用;仅支持同库集合合并,字段缺失补 null,不自动去重或排序,大集合需启用 allowDiskUse: true。

为什么 $unionWith 在 MongoDB 4.4 里不能直接写在顶层?
因为 $unionWith 是聚合阶段(stage),不是独立命令,必须放在 db.collection.aggregate() 管道中使用。直接执行 db.collection.unionWith(...) 或把它当 shell 命令用会报错:unrecognized pipeline stage name: '$unionWith'——这通常意味着你漏了外层的 aggregate() 调用。
它只能合并「同数据库内」的集合,跨库不支持;目标集合和源集合的字段名、类型不要求一致,但字段名相同才可能自然对齐(否则会出现 null 值)。
- 必须以数组形式传入整个聚合管道,
$unionWith是其中一项,例如:[{ $unionWith: { coll: "orders_2023" } }] - 不能在
find()、update()或mapReduce()中使用 - 如果被合并的集合不存在,MongoDB 不报错,而是静默跳过(这点容易误以为数据丢了)
如何用 $unionWith 合并两个结构不完全相同的集合?
字段缺失时自动补 null,不会报错或截断。比如 users 有 name 和 email,admins 有 name 和 role,合并后结果里每条文档都会包含 name、email、role 三个字段,缺失字段值为 null。
若想统一字段含义(比如把 admins.role 映射成 type: "admin"),得在 $unionWith 前或后加 $project 预处理:
db.users.aggregate([
{ $unionWith: {
coll: "admins",
pipeline: [
{ $project: { name: 1, email: { $literal: null }, role: 1 } }
]
}
},
{ $project: { name: 1, email: 1, type: { $cond: { if: { $eq: ["$role", "super"] }, then: "admin", else: "user" } } } }
])
-
pipeline参数是可选的,仅作用于被合并的集合(这里是admins),不影响主集合(users) - 主集合的字段不会被
pipeline修改,所以要统一结构,最好两边都预处理,或在$unionWith后统一$project - 注意
$literal的写法:必须用{ $literal: null },不能直接写null,否则会被忽略
性能和限制:大集合合并时要注意什么?
$unionWith 本身不触发索引,也不做去重,就是逐条拉取+拼接,内存消耗与结果集大小正相关。如果合并后结果超 100MB,默认会失败并报错:Aggregation stage exceeded memory limit。
- 加
allowDiskUse: true是必须的,尤其当任一集合超过几百万文档:db.users.aggregate([...], { allowDiskUse: true }) - 没有内置排序保证,合并后顺序是「主集合全量 + 被合并集合全量」,不按时间、ID 或任何字段自动排序
- 无法在分片集群上跨分片合并(即
coll必须是本分片上的集合),否则报错:unionWith does not support sharded collections - 不支持事务内使用(
$unionWith是只读阶段,但放在事务中会直接拒绝)
替代方案:什么时候不该硬用 $unionWith?
如果你只是想查「用户或管理员」,且集合不大、查询频次低,$unionWith 没问题。但以下情况建议换思路:
- 需要频繁按
email查找 → 把数据归一到一个集合,用 TTL 索引或分区分片管理生命周期 - 要实时去重 →
$unionWith不去重,得套一层$group,但代价高;不如应用层合并或用物化视图 - 跨数据库 → 只能导出再导入,或用应用代码双查+合并,MongoDB 4.4 原生不支持
- 需要写回结果 →
$unionWith是只读的,想存新集合得用$out或$merge,但注意它们会覆盖或更新目标集合,不是追加
最常被忽略的一点:$unionWith 不校验 schema,字段名拼错(比如 emial)只会默默产生一堆 null,查起来像数据丢了——建议合并前先用 sample(1) 分别看两边字段结构。


















