基于值折叠子文档的投影:MongoDB聚合查询技术问询
实现MongoDB子文档数组的折叠投影
没问题,我来帮你搞定这个基于指定部门子集折叠子文档的聚合投影需求!
首先明确你的场景:文档里有dept_ids数组,每个元素是包含dept_id和dept_name的对象,你需要根据已知的部门ID子集,只保留数组里匹配的子文档,也就是所谓的“折叠”操作。
方法一:用$filter快速过滤匹配的子文档
这是最直接高效的方式,在$project阶段使用$filter操作符遍历数组,只保留符合条件的子文档:
db.collection.aggregate([ // 可选:先过滤出至少包含一个目标部门的文档,减少后续处理量 { $match: { "dept_ids.dept_id": { $in: ["dd7867535", "dl97087079"] } // 替换成你的部门ID子集 } }, { $project: { _id: 1, // 保留原文档ID dept_ids: { $filter: { input: "$dept_ids", // 要处理的目标数组 as: "dept", // 遍历元素的别名 cond: { $in: ["$$dept.dept_id", ["dd7867535", "dl97087079"]] } // 判断条件:当前元素的dept_id是否在目标子集里 } } } } ])
代码说明
$match阶段是可选的,但强烈建议加上,它会先筛选出至少包含一个目标部门的文档,避免对完全不相关的文档做投影处理,大幅提升查询性能。$filter会遍历dept_ids数组,只保留dept_id在你指定子集里的子文档,完全保留原有的子文档结构。
方法二:去重+折叠(适合存在重复部门ID的场景)
如果你的文档里dept_ids数组可能存在重复的部门ID(虽然你提到每个部门对应独立ID,但还是提一下这个极端场景),可以用$setUnion先取交集的部门ID,再映射回完整的子文档:
db.collection.aggregate([ { $match: { "dept_ids.dept_id": { $in: ["dd7867535", "dl97087079"] } } }, { $project: { _id: 1, dept_ids: { $map: { // 先获取目标部门子集和原数组dept_id的交集(自动去重) input: { $setUnion: [ { $map: { input: "$dept_ids", as: "d", in: "$$d.dept_id" } }, ["dd7867535", "dl97087079"] ] }, as: "deptId", // 把每个交集的dept_id映射回完整的子文档 in: { $first: { $filter: { input: "$dept_ids", as: "d", cond: { $eq: ["$$d.dept_id", "$$deptId"] } } } } } } } } ])
代码说明
$setUnion会自动去重,确保每个部门ID只出现一次。$map把去重后的部门ID重新映射为完整的dept_id+dept_name对象,用$first取数组里第一个匹配的子文档(因为已经去重,所以只会有一个)。
额外小技巧
如果需要保留原文档的所有其他字段,只修改dept_ids数组,可以用$addFields替代$project,这样就不用手动声明所有要保留的字段了。
内容的提问来源于stack exchange,提问作者user817851
相关产品推荐
相关产品推荐

