MongoDB聚合查询:用$lookup关联集合并分组统计投票数
Mongoose聚合查询实现选项票数统计及占比计算
针对你的需求,这里提供完整的Mongoose聚合查询方案,实现每个投票选项的票数统计、占比计算,同时保留票数为0的选项:
Option.aggregate([ // 关联votes集合,获取对应选项的所有投票记录 { $lookup: { from: "votes", localField: "_id", foreignField: "option", as: "voteDocs" } }, // 计算当前选项的总票数 { $addFields: { totalVotes: { $size: "$voteDocs" } } }, // 聚合所有选项数据,统计总投票数 { $group: { _id: null, options: { $push: "$$ROOT" }, totalAllVotes: { $sum: "$totalVotes" } } }, // 展开选项数组,回到单文档结构 { $unwind: "$options" }, // 计算投票占比,处理总票数为0的边界情况 { $addFields: { votePercentage: { $cond: { if: { $eq: ["$totalAllVotes", 0] }, then: "0", else: { $toString: { $round: { $multiply: [{ $divide: ["$options.totalVotes", "$totalAllVotes"] }, 100] } } } } } } }, // 整理输出字段,匹配目标格式 { $replaceWith: { _id: "$options._id", name: "$options.name", totalVotes: "$options.totalVotes", votePercentage: "$votePercentage" } }, // 按票数降序排序,和示例结果顺序一致 { $sort: { totalVotes: -1 } } ]) .then(result => console.log(result)) .catch(err => console.error(err));
各阶段说明:
- $lookup:通过
options._id与votes.option关联,把匹配到的投票文档存入voteDocs数组。 - $addFields:用
$size获取voteDocs的长度,得到当前选项的totalVotes。 - $group:将所有数据聚合为一个分组,保存所有选项数据到
options数组,同时计算全局总票数totalAllVotes。 - $unwind:拆分
options数组,让每个选项回到独立文档结构,方便后续计算占比。 - $addFields:计算单选项票数占总票数的比例,乘以100后取整并转为字符串;如果总票数为0,直接返回"0"避免除以0错误。
- $replaceWith:仅保留目标字段,调整文档结构与需求一致。
- $sort:按
totalVotes降序排列,匹配示例结果的顺序。
注意事项:
- 确保
$lookup中的from参数与你的votes集合名称一致(Mongoose默认会将模型名转为小写复数作为集合名)。 - 示例中的百分比数值(35、25)可能是笔误,按真实票数计算的话,总票数5,A的3票占60%,C的2票占40%,如果需要自定义百分比逻辑,可以调整
$multiply或$round的参数。
内容的提问来源于stack exchange,提问作者Deelm
相关产品推荐
相关产品推荐

