MongoDB聚合:过滤数组元素后保留所有原字段的方法
解决方案
方法一:用$filter直接过滤数组(推荐)
完全不需要拆分组装,直接在原文档上替换report字段为过滤后的数组,所有原有字段会自动保留:
.aggregate([ { $addFields: { report: { $filter: { input: "$report", cond: { $eq: ["$$this.m_name", "ABC"] } } } } } ])
逻辑说明:
$addFields会保留所有原有字段,同时将report字段替换为过滤后的结果$filter遍历report数组,仅保留m_name等于"ABC"的元素
方法二:基于原unwind+group的改进方案
如果一定要沿用原来的拆分组装思路,也可以用$mergeObjects结合$$ROOT批量保留所有字段,无需逐个指定:
.aggregate([ { $unwind: "$report" }, { $match: { "report.m_name": "ABC" } }, { $group: { _id: "$_id", root: { $first: "$$ROOT" }, filteredReports: { $push: "$report" } } }, { $replaceRoot: { newRoot: { $mergeObjects: ["$root", { report: "$filteredReports" }] } } } ])
逻辑说明:
- 先通过
unwind拆分数组,再用match过滤出符合条件的report元素 - 分组时用
$first: "$$ROOT"保留同一_id下的完整原始文档(其余字段值均一致),同时收集过滤后的report到新数组 - 最后用
$replaceRoot和$mergeObjects将原始文档字段与新的report数组合并,替换原report字段
对比来看,方法一性能更优,避免了unwind和group的额外开销,代码也更简洁。
内容的提问来源于stack exchange,提问作者ELsssss
相关产品推荐
相关产品推荐

