如何在MongoDB中使用Group分组查询按城市统计消费总金额?
MongoDB $group 聚合实现按城市统计总价
前置注意事项
你当前定义的Schema中price字段为String类型,直接参与数值求和会出现计算异常,优先建议将该字段类型修改为Number,减少聚合时的类型转换开销。如果暂时无法调整Schema结构,可以在聚合阶段增加类型转换逻辑兼容。
$group 核心逻辑说明
$group是MongoDB聚合管道的核心阶段之一,作用是按指定的分组键对文档归类,配合累加器完成同组数据的统计计算:
_id字段为必填项,用于指定分组依据的字段,这里按城市分组就填'$city'- 累加器支持求和、平均值、最大/最小值等统计场景,本次需求用
$sum累加器计算同组价格总和即可
可直接运行的实现代码
方案1:修改Schema为最优实现(推荐)
先调整Schema定义,将price改为数值类型:
const historySchema = mongoose.Schema( { city: { type: String, required: true }, price: { type: Number, required: true }, // 调整为Number类型存储数值 customerId: {type: String, required: true} }, ); const History = mongoose.model('History', historySchema);
编写聚合查询+结果格式转换逻辑:
async function getCityPriceTotal() { // 执行聚合查询 const aggRes = await History.aggregate([ { $group: { _id: '$city', // 按city字段分组 totalPrice: { $sum: '$price' } // 累加同组所有文档的price值 } } ]); // 将聚合返回的数组转换为你需要的键值对结构 const finalResult = {}; aggRes.forEach(item => { finalResult[item._id] = item.totalPrice; }); return finalResult; }
方案2:兼容String类型price的实现
如果暂时无法修改Schema字段类型,可以在聚合时增加类型转换,避免计算错误:
async function getCityPriceTotal() { const aggRes = await History.aggregate([ { $group: { _id: '$city', totalPrice: { $sum: { $convert: { input: '$price', to: 'double', // 将字符串类型的price转为双精度数值 onError: 0, // 遇到非数字内容时默认按0计算,避免聚合中断 onNull: 0 // 字段为空时默认按0计算 } } } } } ]); const finalResult = {}; aggRes.forEach(item => { finalResult[item._id] = item.totalPrice; }); return finalResult; }
最终返回格式
调用上述方法后,得到的返回结果完全匹配你的需求:
{ "City A": 1000, "City B": 2000, "City C": 3000 }
内容的提问来源于stack exchange,提问作者Alchemist
相关产品推荐
相关产品推荐

