如何通过Node API结合Mongoose实现已付/未付客户统计及数据返回?
实现已付款/未付款客户列表及统计的最优方案
看起来你已经在使用Mongoose的aggregate方法了,只需要调整聚合阶段就能一次性拿到已付款/未付款客户列表+对应统计数量,不需要多次查询,这也是性能最优的方案。
完整实现代码
router.get("/", ensureAuthenticated, async (req, res) => { try { // 一次聚合完成分组统计+客户列表收集 const aggregateResult = await Loan.aggregate([ // 可选:如果需要额外过滤条件(比如特定时间范围、特定用户),可以在这里加$match // { $match: { /* 过滤规则 */ } }, { $group: { _id: "$ePaidunpaid", // 按付款状态分组(比如"Paid"和"Unpaid") totalCount: { $sum: 1 }, // 统计该状态下的客户数量 customerList: { $push: "$$ROOT" } // 收集该状态下的所有客户完整数据 } }, // 可选:重命名字段让结果更直观 { $project: { paymentStatus: "$_id", totalCount: 1, customerList: 1, _id: 0 } } ]); // 把数组结果转成对象,方便模板直接调用 const statusData = {}; aggregateResult.forEach(item => { statusData[item.paymentStatus.toLowerCase()] = item; }); // 处理无数据的情况,避免模板报错 const paidData = statusData.paid || { totalCount: 0, customerList: [] }; const unpaidData = statusData.unpaid || { totalCount: 0, customerList: [] }; res.render("dashboard", { admin: req.user.eUserType, user: req.user, paidData, unpaidData }); } catch (err) { console.error("聚合查询失败:", err); res.status(500).send("服务器查询出错"); } });
关键代码解释
$group阶段:_id: "$ePaidunpaid":以ePaidunpaid字段的值为分组依据,自动把"Paid"和"Unpaid"的客户分成两组totalCount: { $sum: 1 }:每组内每有一条数据就累加1,最终得到对应状态的客户总数customerList: { $push: "$$ROOT" }:把分组内的完整文档($$ROOT代表当前整条数据)存入数组,直接拿到该状态下的所有客户列表
- 结果转换:把聚合返回的数组转成对象,方便在模板里直接用
paidData.totalCount、unpaidData.customerList这类直观的变量调用 - 异常处理:用
async/await替代原有的then链式调用,代码更易读,也能统一捕获查询错误
性能优化建议
如果你的Loan集合数据量很大,建议给ePaidunpaid字段添加索引,大幅提升聚合查询的速度:
// 在Loan模型定义时添加索引 LoanSchema.index({ ePaidunpaid: 1 });
简化方案(仅需统计数量)
如果只是需要统计两类客户的数量,不需要完整列表,可以去掉$push操作,进一步提升性能:
const countResult = await Loan.aggregate([ { $group: { _id: "$ePaidunpaid", totalCount: { $sum: 1 } } } ]);
内容的提问来源于stack exchange,提问作者Nikhil Savaliya
相关产品推荐
相关产品推荐

