如何用MongoDB聚合分组含字符串/数组类型标识符的文档?
可行方案:MongoDB按混合类型identifier分组
你的需求完全可以实现,核心是先统一identifier的格式,再通过图查找处理连通的identifier分组,最终合并对应的participants。以下是针对你示例数据的完整聚合查询:
db.your_collection.aggregate([ // 统一identifier为数组格式(字符串转单元素数组) { $addFields: { normalizedIdentifiers: { $cond: { if: { $isArray: "$identifier" }, then: "$identifier", else: ["$identifier"] } } } }, // 展开数组,让每个identifier单独成为一条记录 { $unwind: "$normalizedIdentifiers" }, // 查找所有连通的identifier对应的文档(形成关联组) { $graphLookup: { from: "your_collection", // 替换为你的集合名称 startWith: "$normalizedIdentifiers", connectFromField: "normalizedIdentifiers", connectToField: "normalizedIdentifiers", as: "connectedDocuments", maxDepth: 10 // 根据你的数据关联深度调整,确保覆盖所有连通情况 } }, // 合并组内所有唯一的identifier和participants { $addFields: { allIdentifiers: { $reduce: { input: "$connectedDocuments", initialValue: [], in: { $setUnion: ["$$value", "$$this.normalizedIdentifiers"] } } }, allParticipants: { $reduce: { input: "$connectedDocuments", initialValue: [], in: { $setUnion: ["$$value", "$$this.participants"] } } } } }, // 按合并后的identifier组去重 { $group: { _id: "$allIdentifiers", participants: { $first: "$allParticipants" } } }, // (可选)对participants排序,优化结果展示 { $addFields: { participants: { $sortArray: { input: "$participants", sortBy: 1 } } } } ])
各阶段说明:
- 统一格式:通过
$addFields和$cond,把字符串类型的identifier转为单元素数组,确保后续处理格式一致。 - 展开数组:
$unwind将数组拆分,让每个identifier都能作为关联查询的起点。 - 图查找关联组:
$graphLookup是关键,它会找到所有与当前identifier连通的文档——只要两个文档共享任意一个identifier(或通过其他文档间接共享),就会被归为同一组。 - 合并去重:用
$reduce和$setUnion合并组内的所有identifier和participants,自动去除重复值。 - 去重重复组:因为展开后每个identifier都会生成一条组记录,最后通过
$group按合并后的identifier组去重,得到最终的唯一分组。
执行上述查询后,将得到你预期的结果:
{ "_id" : [ "919f77bc-adca-4cbc-ac38-9139552cdb5b", "b553622e-b1c9-4030-8460-a7783214359b" ], "participants" : ["p1", "p2", "p3"] }, { "_id" : [ "9837dac78-4cbc-dsa38-9139552cd564" ], "participants" : [ "p2", "p3" ] }
内容的提问来源于stack exchange,提问作者user6627352
相关产品推荐
相关产品推荐

