如何在Mongo Shell中检测Mongo文档的重复属性及数组元素
检测MongoDB文档中inventory数组的重复属性问题
问题1:检测inventory子文档内部的重复键(如单个元素里重复的name/skd)
使用以下聚合查询可定位到具体文档和数组索引位置的重复键:
db.mycollection.aggregate([ // 展开inventory数组并保留元素索引 { $unwind: { path: "$inventory", includeArrayIndex: "elementIndex" } }, // 将子文档转为键值对数组,方便统计键的出现次数 { $addFields: { inventoryKeys: { $objectToArray: "$inventory" } } }, // 展开键值对数组 { $unwind: "$inventoryKeys" }, // 按文档ID、元素索引、键名分组,统计每个键的出现次数 { $group: { _id: { docId: "$_id", index: "$elementIndex", key: "$inventoryKeys.k" }, occurrenceCount: { $sum: 1 } } }, // 筛选出现次数大于1的重复键 { $match: { occurrenceCount: { $gt: 1 } } }, // 格式化输出结果 { $project: { _id: 0, 文档ID: "$_id.docId", 数组元素索引: "$_id.index", 重复键名: "$_id.key", 出现次数: "$occurrenceCount" } } ])
针对示例文档,查询会返回:
{ "文档ID": ObjectId("65498654654"), "数组元素索引": 0, "重复键名": "name", "出现次数": 2 }, { "文档ID": ObjectId("65498654654"), "数组元素索引": 0, "重复键名": "skd", "出现次数": 2 }
问题2:检测不同inventory元素之间重复的skd值
使用以下聚合查询可找出跨元素的skd重复:
db.mycollection.aggregate([ // 展开inventory数组并保留元素索引 { $unwind: { path: "$inventory", includeArrayIndex: "elementIndex" } }, // 按文档ID和skd值分组,收集对应的元素索引并统计次数 { $group: { _id: { docId: "$_id", skdValue: "$inventory.skd" }, 涉及元素索引: { $push: "$elementIndex" }, 出现次数: { $sum: 1 } } }, // 筛选出现次数大于1的skd值 { $match: { 出现次数: { $gt: 1 } } }, // 格式化输出 { $project: { _id: 0, 文档ID: "$_id.docId", 重复skd值: "$_id.skdValue", 涉及元素索引: "$涉及元素索引", 出现次数: "$出现次数" } } ])
针对示例文档,查询会返回:
{ "文档ID": ObjectId("65498654654"), "重复skd值": "321654", "涉及元素索引": [1, 2], "出现次数": 2 }
原查询失效的原因
- 未处理子文档内部的重复键:原查询仅针对
inventory.name的值重复,无法检测同一个子文档中存在多个name或skd键的情况。 - 未保留数组索引:无法定位到具体是数组的第几个元素出现问题。
- 未覆盖skd值跨元素重复的检测逻辑。
内容的提问来源于stack exchange,提问作者Johan Camargo
相关产品推荐
相关产品推荐

