如何在Mongoose聚合的$match阶段未匹配到文档时抛出错误?
解决方案
要实现指定userId对应用户不存在时抛出错误并提示客户端,你需要先区分「用户不存在」和「用户存在但无登录尝试」这两种情况——直接使用aggregate的话,两种场景都会返回空数组,无法直接判断原因。下面提供两种可行方案:
方法一:先验证用户存在性,再执行聚合查询
这种方式逻辑直观,代码复杂度低,额外的主键查询性能开销极小:
app.get('/users/:userId/login-attempts', async(req,res,next)=>{ try { // 基于_id主键快速验证用户是否存在 const userExists = await User.exists({ _id: mongoose.Types.ObjectId(req.params.userId) }); if (!userExists) { const error = new Error(`用户ID ${req.params.userId} 不存在`); error.statusCode = 404; throw error; } // 用户存在时,执行聚合查询提取登录记录 const loginAttempts = await User.aggregate([ { $match: { _id: mongoose.Types.ObjectId(req.params.userId) } }, { $unwind: '$loginAttempts' }, { $replaceRoot: { newRoot: '$loginAttempts' } }, ]); // 返回结果,空数组代表用户存在但无登录尝试 res.status(200).json({ loginAttempts }); } catch (err) { // 将错误传递到Express全局错误处理中间件 next(err); } })
方法二:在聚合管道中保留用户存在标记(单次数据库请求)
如果希望减少数据库请求次数,可以修改聚合管道,通过$group和$addFields保留用户存在的状态:
app.get('/users/:userId/login-attempts', async(req,res,next)=>{ try { const result = await User.aggregate([ { $match: { _id: mongoose.Types.ObjectId(req.params.userId) } }, // 添加标记字段,确认用户存在 { $addFields: { userExists: true } }, // 保留空数组的情况,避免直接过滤掉存在但无登录记录的用户 { $unwind: { path: '$loginAttempts', preserveNullAndEmptyArrays: true } }, // 聚合用户信息和登录记录 { $group: { _id: '$_id', userExists: { $first: '$userExists' }, loginAttempts: { $push: '$loginAttempts' } } }, // 过滤掉空的登录记录,整理返回结构 { $project: { _id: 0, userExists: 1, loginAttempts: { $filter: { input: '$loginAttempts', cond: { $ne: ['$$this', null] } } } } } ]); if (result.length === 0) { // 无聚合结果说明用户不存在 const error = new Error(`用户ID ${req.params.userId} 不存在`); error.statusCode = 404; throw error; } // 返回整理后的登录记录 res.status(200).json({ loginAttempts: result[0].loginAttempts }); } catch (err) { next(err); } })
补充:全局错误处理
最后需要配置Express全局错误处理中间件,统一将错误返回给客户端:
app.use((err, req, res, next) => { const statusCode = err.statusCode || 500; const message = err.message || '服务器内部错误'; res.status(statusCode).json({ error: message }); });
内容的提问来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

