Mongoose密码字段设select:false后调用create方法仍返回该字段如何解决
问题原因
Mongoose中给字段设置select: false属性仅对find、findOne、findById等查询类操作生效,create()方法执行的是写入操作,返回的是刚写入数据库的完整原始文档,不会触发select属性的过滤逻辑,所以会携带password字段。
可选解决方案
方案1:返回前手动删除password字段
直接在返回响应前对create()返回的文档处理,删除password字段即可,修改控制器代码如下:
exports.registerUser = asyncHandler(async (req, res, next) => { const user = await User.create(req.body); // 手动删除密码字段,mongoose返回的文档原始数据存在_doc属性中 delete user._doc.password; res.status(200).json({ success: true, message: user }); });
这种方法适合只需要在单个接口处理的场景,逻辑简单直接。
方案2:创建完成后重新发起查询
写入完成后调用findById查询一次新创建的用户,此时select: false会生效自动过滤password字段:
exports.registerUser = asyncHandler(async (req, res, next) => { const createdUser = await User.create(req.body); // 重新查询触发select规则 const user = await User.findById(createdUser._id); res.status(200).json({ success: true, message: user }); });
方案3:全局配置Schema转JSON时自动移除密码
给UserSchema添加toJSON转换钩子,所有返回用户文档转JSON的场景都会自动删除password,无需每个接口单独处理,在Schema定义文件中添加如下配置即可:
// 放在UserSchema定义完成后,导出模型之前 UserSchema.set('toJSON', { transform: (doc, ret) => { // 移除password字段 delete ret.password; // 也可以在这里统一移除其他不需要返回的字段,比如__v等 delete ret.__v; return ret; } });
这种方法适合全项目所有返回用户信息的场景都需要隐藏密码的情况,一次配置全局生效。
内容的提问来源于stack exchange,提问作者Bryanjl
相关产品推荐
相关产品推荐

