Node.js基于Mongoose的评分平均计算异常问题求助
问题根因
你遇到的计算异常本质是字符串拼接而非数值相加导致的:
- 前端提交到
req.body的所有criteria参数的值都是字符串类型(比如"8"而非数字8) - 你写的
avg函数直接执行a + b,如果操作数是字符串就会触发拼接逻辑:10个"8"相加会得到"8888888888",除以10得到888888888.8,再和"8"拼接得到"888888888.88",最后除以2就得到了你看到的4444444这类异常值。
修复方案
1. 快速修复:直接转换数值类型
在取值的时候统一把字符串转成数字即可,修改你创建Rates实例的部分:
const rate = new Rates({ project, voter, votes:{ participant: participants[i], // 每个criteria取值时转成数字 criteria1: Number(criteria1[i]), criteria2: Number(criteria2[i]), criteria3: Number(criteria3[i]), criteria4: Number(criteria4[i]), criteria5: Number(criteria5[i]), criteria6: Number(criteria6[i]), criteria7: Number(criteria7[i]), criteria8: Number(criteria8[i]), criteria9: Number(criteria9[i]), criteria10: Number(criteria10[i]), criteria11: Number(criteria11[i]), criteria12: criteria12[i], // 计算时也统一转数字避免出错 average: avg([ avg([criteria1, criteria2, criteria3, criteria4, criteria5, criteria6, criteria7, criteria8, criteria9, criteria10].map(c => Number(c[i]))), Number(criteria11[i]) ]) } })
2. 优化方案:改造avg函数从根源避免类型问题
可以给avg函数加上数值转换逻辑,以后不管传的是字符串还是数字都能正常计算,非法数值默认按0处理,可根据业务需求调整:
const avg = (args) => { const numbers = args.map(item => Number(item) || 0); return numbers.reduce((a, b) => a + b, 0) / numbers.length; };
改造后你原来的计算代码不用修改也能正常输出正确结果。
额外优化建议
你现在手写10个criteria的方式冗余度很高,可以改成动态取值,后续增减评分项也不用改逻辑:
// 动态生成criteria1到criteria10的数值数组 const firstTen = Array.from({length:10}, (_, idx) => Number(req.body[`criteria${idx+1}`][i])); const firstAvg = avg(firstTen); const finalAvg = avg([firstAvg, Number(criteria11[i])]);
内容的提问来源于stack exchange,提问作者Ayaz
相关产品推荐
相关产品推荐

