You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用$unwind快速识别嵌套数组含重复a.p.id的MongoDB文档

不使用$unwind匹配嵌套数组中存在重复字段的MongoDB文档

可以不依赖$unwind实现需求,下面是基于$reduce、$addToSet等数组操作符的高效聚合方案,避免了$unwind带来的文档爆炸问题,在大数据量场景下性能更优。

方案1:输出精简格式({ key:2 , id:3 })

db.collection.aggregate([
  {
    $addFields: {
      duplicateIds: {
        $reduce: {
          input: "$a",
          initialValue: { allIds: [], duplicates: [] },
          in: {
            $let: {
              vars: {
                currentPIds: "$p.id",
                newAllIds: { $concatArrays: ["$$value.allIds", "$$currentPIds"] },
                uniqueIds: { $addToSet: "$$newAllIds" },
                duplicates: {
                  $setDifference: [
                    "$$newAllIds",
                    "$$uniqueIds"
                  ]
                }
              },
              in: {
                allIds: "$$newAllIds",
                duplicates: { $addToSet: "$$duplicates" }
              }
            }
          }
        }
      }
    }
  },
  {
    $match: {
      "duplicateIds.duplicates": { $ne: [] }
    }
  },
  {
    $project: {
      key: 1,
      duplicateIds: {
        $reduce: {
          input: "$duplicateIds.duplicates",
          initialValue: [],
          in: { $concatArrays: ["$$value", "$$this"] }
        }
      }
    }
  },
  {
    $unwind: "$duplicateIds"
  },
  {
    $group: {
      _id: "$key",
      ids: { $addToSet: "$duplicateIds" }
    }
  },
  {
    $project: {
      _id: 0,
      key: "$_id",
      id: { $arrayElemAt: ["$ids", 0] }
    }
  }
])

步骤拆解:

  • $addFields:遍历外层数组a,收集所有p.id到临时数组allIds;通过$addToSet生成去重后的id列表,再用$setDifference找出重复的id值,存入duplicates。
  • $match:过滤出确实存在重复id的文档。
  • $project:把嵌套的重复id数组扁平化,得到所有重复id的集合。
  • $unwind + $group:对重复id去重,确保每个key对应唯一的重复id。
  • $project:整理成你需要的{ key, id }格式。

方案2:返回完整匹配文档

如果需要返回完整的源文档,只需调整聚合管道的最后几个阶段:

db.collection.aggregate([
  {
    $addFields: {
      duplicateIds: {
        $reduce: {
          input: "$a",
          initialValue: { allIds: [], duplicates: [] },
          in: {
            $let: {
              vars: {
                currentPIds: "$p.id",
                newAllIds: { $concatArrays: ["$$value.allIds", "$$currentPIds"] },
                uniqueIds: { $addToSet: "$$newAllIds" },
                duplicates: {
                  $setDifference: [
                    "$$newAllIds",
                    "$$uniqueIds"
                  ]
                }
              },
              in: {
                allIds: "$$newAllIds",
                duplicates: { $addToSet: "$$duplicates" }
              }
            }
          }
        }
      }
    }
  },
  {
    $match: {
      "duplicateIds.duplicates": { $ne: [] }
    }
  },
  {
    $project: {
      duplicateIds: 0 // 可选:移除临时生成的duplicateIds字段
    }
  }
])

这个方案全程在单文档内完成数组运算,不会像$unwind那样拆分文档,处理大数组时性能提升明显。

内容的提问来源于stack exchange,提问作者R2D2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:22:29