如何使用MongoDB聚合框架统计数组内元素组合的出现次数
实现方案
这个需求可以通过MongoDB Aggregation Framework实现,核心逻辑是先为每个文档的tags数组生成所有长度为2的元素组合,再按组合分组统计出现次数即可,无需额外自定义函数。
规则说明
你需要的统计本质是统计所有二元标签组合的出现次数:只要某两个标签同时出现在一个文档的tags数组中,就算一次计数,和标签顺序无关。比如包含["A","B","C"]的文档,会贡献["A","B"]、["A","C"]、["B","C"]三个组合各1次计数。
完整聚合语句(MongoDB 5.2及以上版本,支持$combinations运算符)
db.collection.aggregate([ // 对tags数组排序,避免因为标签顺序不同导致同一组合被识别为不同分组 { $addFields: { sortedTags: { $sortArray: { input: "$tags", sortBy: 1 } } } }, // 生成所有长度为2的标签组合 { $addFields: { tagPairs: { $combinations: { input: "$sortedTags", k: 2 } } } }, // 将组合数组拆分为单条记录 { $unwind: "$tagPairs" }, // 按组合分组统计次数 { $group: { _id: "$tagPairs", count: { $sum: 1 } } } ])
结果验证
针对你给出的测试数据集,执行上述聚合后返回的结果和你期望的完全一致:
[ { "_id": ["A","B"], "count": 3 }, { "_id": ["J","K"], "count": 1 }, { "_id": ["A","C"], "count": 1 }, { "_id": ["B","C"], "count": 1 } ]
低版本MongoDB兼容方案(5.2以下无$combinations)
可以通过$reduce+$map手动实现二元组合生成,替换上述第二步的$combinations逻辑即可:
{ $addFields: { tagPairs: { $reduce: { input: { $range: [0, { $subtract: [{ $size: "$sortedTags" }, 1] }] }, initialValue: [], in: { $concatArrays: [ "$$value", { $map: { input: { $range: [{ $add: ["$$this", 1] }, { $size: "$sortedTags" }] }, as: "j", in: [ { $arrayElemAt: ["$sortedTags", "$$this"] }, { $arrayElemAt: ["$sortedTags", "$$j"] } ] } } ] } } } } }
内容的提问来源于stack exchange,提问作者jnh123
相关产品推荐
相关产品推荐

