MongoDB聚合Facet子管道结果按员工名称关联合并的实现问询
MongoDB Facet结果关联合并方案
问题场景
集合文档结构:
type: 可选值为a1或a2 emp_name: 字符串类型 status: 可选值为0或1
当前使用$facet定义了两个子管道:
- a1子管道:过滤
type=a1的数据,按emp_name分组统计数量,最终输出empName和count字段 - a2子管道:过滤
type=a2的数据,输出type、emp_name、status字段
现在需要将两个子管道的结果按empName(a1)和emp_name(a2)匹配,合并为包含empName、count、type、status的单个对象。
解决方案
可以通过在$facet之后添加额外聚合阶段实现关联合并,完整管道如下:
[ { $facet: { a1: [ { $match: { type: "a1" } }, { $group: { _id: "$emp_name", count: { $sum: 1 } } }, { $project: { empName: "$_id", count: 1, _id: 0 } } ], a2: [ { $match: { type: "a2" } }, { $project: { emp_name: 1, status: 1, type: 1, _id: 0 } } ] } }, { $unwind: "$a1" }, { $lookup: { from: { $literal: "$$CURRENT.a2" }, localField: "a1.empName", foreignField: "emp_name", as: "matchedA2" } }, { $unwind: { path: "$matchedA2", preserveNullAndEmptyArrays: true } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$a1", { type: "$matchedA2.type", status: "$matchedA2.status", empName: { $ifNull: ["$a1.empName", "$matchedA2.emp_name"] } } ] } } } ]
关键步骤说明
- 优化a1子管道:将
$group的_id直接设为$emp_name,简化后续投影逻辑 - $unwind展开a1数组:将a1的每个统计对象单独拆分,便于逐个关联
- $lookup关联a2数据:利用
$literal引用当前文档的a2数组作为关联数据源,通过empName和emp_name匹配 - 保留无匹配记录:
preserveNullAndEmptyArrays: true确保即使a1的员工在a2中无对应数据,也不会丢失统计记录 - 合并字段到根对象:通过
$mergeObjects整合a1和匹配到的a2字段,用$ifNull保证empName字段统一存在
如果需要保留a2中无对应a1统计的记录,可以调整管道顺序,先展开a2再关联a1,或者添加额外逻辑处理双向合并。
内容的提问来源于stack exchange,提问作者Prakash
相关产品推荐
相关产品推荐

