You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Mongoose的schema.pre(/^find/)中间件创建特定调用例外?

解决Mongoose pre(/^find/)中间件在特定查询时的例外问题

你遇到的核心问题是全局的pre(/^find/)中间件过滤掉了active: false的用户,导致登录时无法查询到已标记为非活跃的账号进行重新激活。下面给出两种可行的解决方案:

方案一:给Query添加自定义跳过标志(推荐)

通过给Mongoose的Query对象添加一个自定义标志,让pre(/^find/)中间件根据这个标志决定是否执行过滤逻辑,语义清晰且可复用性强。

修改Schema中间件

userSchema.pre(/^find/, function (next) {
  // 仅当没有设置_skipActiveFilter标志时,才执行active过滤
  if (!this._skipActiveFilter) {
    this.find({ active: { $ne: false } });
  }
  next();
});

// 给Query原型添加方法,用于设置跳过标志
userSchema.query.skipActiveFilter = function () {
  this._skipActiveFilter = true;
  return this; // 支持链式调用
};

修改登录逻辑中的查询

在登录时调用skipActiveFilter()方法,绕过active过滤:

exports.login = catchAsync(async (req, res, next) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return next(new AppError('Please provide email and password', 400));
  }

  // 添加skipActiveFilter()方法,跳过pre中间件的active过滤
  const user = await User.findOne({ email }).skipActiveFilter().select('+password');

  if (!user || !(await user.correctPassword(password, user.password))) {
    return next(new AppError('Incorrect email or password', 401));
  }

  // 重新激活账号
  await User.findByIdAndUpdate(user.id, { active: true });
  createSendToken(user, 200, res);
});

方案二:查询时显式包含非活跃用户

如果不想修改Schema中间件,可以在登录查询中直接指定active的范围,覆盖中间件的过滤条件:

exports.login = catchAsync(async (req, res, next) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return next(new AppError('Please provide email and password', 400));
  }

  // 查询时同时包含active为true和false的用户
  const user = await User.findOne({ 
    email, 
    active: { $in: [true, false] } 
  }).select('+password');

  if (!user || !(await user.correctPassword(password, user.password))) {
    return next(new AppError('Incorrect email or password', 401));
  }

  await User.findByIdAndUpdate(user.id, { active: true });
  createSendToken(user, 200, res);
});

方案对比

  • 方案一:语义化强,后续其他需要绕过过滤的场景直接调用skipActiveFilter()即可,低耦合。
  • 方案二:快速实现,但查询条件与中间件逻辑耦合,若后续中间件过滤规则变更,需要同步修改查询条件。

内容的提问来源于stack exchange,提问作者axoiutku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:27:39