MongoDB 4.0.23三层嵌套数组提取sId的高效查询方案
MongoDB 4.0 高性能查询方案
你的场景下性能瓶颈来自多层$unwind拆分大数组产生的海量临时中间文档,以下方案完全复用现有索引,全程避免对大数组做拆分,性能相比双unwind方案有数量级提升。
核心思路
- 前置
$match直接命中你已创建的_a._p._pId.CC索引,从存储层就过滤掉所有不满足条件的文档,不加载无关数据到内存 - 用
$filter+$reduce+$concatArrays在单文档内完成数组的逐层筛选、合并,全程不拆分大数组 - 仅对最终筛选出的极少量目标结果做拆分输出,几乎无额外开销
可直接运行的聚合管道
db.yourCollection.aggregate([ // 索引命中阶段:前置过滤无关文档 { $match: { "_a._p._pId.CC": "CA" } }, // 数组处理阶段:逐层筛选符合条件的元素,合并所有目标t数组 { $project: { matchedT: { $reduce: { input: { $filter: { input: "$_a", cond: { $gt: [ { $size: { $filter: { input: "$$this._p", cond: { $eq: ["$$this._pId.CC", "CA"] } } } }, 0 ] } } }, initialValue: [], in: { $concatArrays: [ "$$value", { $reduce: { input: { $filter: { input: "$$this._p", cond: { $eq: ["$$this._pId.CC", "CA"] } } }, initialValue: [], in: { $concatArrays: [ "$$value", "$$this.s.c.t", "$$this.s.a.t", "$$this.s.d.t" ] } } } ] } } } } }, // 筛选目标t元素,提取sId { $project: { result: { $map: { input: { $filter: { input: "$matchedT", cond: { $and: [ { $eq: ["$$this.language", "CA"] }, { $eq: ["$$this.format", "A4"] } ] } } }, in: { sId: "$$this.sId" } } } } }, // 拆分最终结果输出(仅处理少量符合条件的元素,无性能压力) { $unwind: "$result" }, { $replaceRoot: { newRoot: "$result" } } ])
性能说明
- 管道第一阶段直接走索引,不会做全表扫描,和普通等值查询性能一致
- 数组处理阶段所有计算都在单文档内存中完成,不会产生笛卡尔积式的临时文档,相比两次
$unwind拆分_a、_p大数组的方案,计算量和内存占用可以降低90%以上 - 最后一步
$unwind处理的是已经筛选完成的结果集,单文档对应的结果通常只有个位数,开销可以忽略
如果后续s路径下新增其他存储t数组的字段,只需要在$concatArrays参数中追加对应字段路径即可,不需要调整整体管道逻辑。
内容的提问来源于stack exchange,提问作者R2D2
相关产品推荐
相关产品推荐

