Mongoose/NodeJS中按类型分组计算子文档各分类金额占比问题
解决方案
方案1:直接修改MongoDB聚合管道(一步拿到目标格式)
return User.aggregate([ // 1. 匹配指定ID的用户 { $match: { _id : ObjectId(request.params.id) } }, // 2. 展开交易数组 { $unwind : "$transactions" }, // 3. 按交易类型分组,同时保留邮箱,计算该类型总金额,收集分类明细 { $group: { _id: { type: "$transactions.categoryType", email: "$email" }, totalTypeAmount: { $sum: "$transactions.amount" }, categoryDetails: { $push: { name: "$transactions.categoryName", amount: "$transactions.amount" } } } }, // 4. 计算每个分类的百分比,转换为[分类名, 百分比]的格式 { $project: { _id: 0, email: "$_id.email", type: "$_id.type", categoryPercent: { $map: { input: "$categoryDetails", in: [ "$$this.name", { $round: [ { $multiply: [ { $divide: [ "$$this.amount", "$totalTypeAmount" ] }, 100 ] }, 2 ] } ] } } } }, // 5. 按邮箱合并收入、支出两类数据 { $group: { _id: "$email", Income: { $push: { $cond: [ { $eq: [ "$type", "Income" ] }, "$categoryPercent", "$$REMOVE" ] } }, Expense: { $push: { $cond: [ { $eq: [ "$type", "Expense" ] }, "$categoryPercent", "$$REMOVE" ] } } } }, // 6. 整理为最终输出格式 { $project: { _id: 0, email: "$_id", Income: { $first: "$Income" }, Expense: { $first: "$Expense" } } } ])
方案2:对现有查询结果做代码后处理
如果你不想修改现有聚合逻辑,也可以直接在Node.js层面对拿到的结果做转换,示例代码如下:
// 现有聚合查询返回的结果存在rawResult变量中 // 先查询对应用户的邮箱,也可以调整现有聚合在分组时保留email字段 const user = await User.findById(request.params.id, 'email'); const processedResult = { email: user.email }; rawResult.forEach(typeItem => { processedResult[typeItem.type] = typeItem.transactions.map(tran => [ tran.categoryName, Number((tran.amount / typeItem.total * 100).toFixed(2)) ]); }); // processedResult就是你需要的目标格式
内容的提问来源于stack exchange,提问作者chmscrbbrfck
相关产品推荐
相关产品推荐

