Mongoose执行create创建用户时如何避免返回password字段
Mongoose create返回结果移除password字段实现方案
核心原因
之前尝试的方案不生效,本质是没搞懂Mongoose的几个运行逻辑:
- Schema里给字段设
select: false,只对find/findOne/findById这类读操作查询生效,create/save写操作返回的是内存里刚生成的完整文档实例,根本不会走字段选择逻辑,所以这个配置对create返回结果没用。 - 在
post('save')中间件直接写delete doc.password删不掉字段,是因为doc是Mongoose的Document实例,password是原型上挂载的访问器属性,不是普通对象的自有属性,直接delete碰不到实例内部存的真实数据。 - 把password设为
null只是改了字段值,字段本身还存在,属于凑合用的临时方案,不是真的移除。
落地方法
方法1:仅处理create场景
改动最小,只需要在create拿到文档后,先转成普通JS对象再删字段即可:
module.exports.save = async function(userData){ const userDoc = await User.create(userData); const userRes = userDoc.toObject(); delete userRes.password; return userRes; }
方法2:全局自动过滤(推荐)
直接在Schema定义时加toObject、toJSON转换钩子,不管是create返回、查询返回,只要文档转普通对象、转JSON(Express/Koa等框架接口返回JSON时会自动触发toJSON),都会自动删掉password字段,不用每个接口单独写逻辑:
const UserSchema = new mongoose.Schema({ password: { type: String, required: true, select: false, }, }, { toObject: { transform(_, ret) { delete ret.password; return ret; } }, toJSON: { transform(_, ret) { delete ret.password; return ret; } } }); const User = mongoose.model('User', UserSchema);
配完之后原有的save方法不用改,直接return await User.create(userData)就会自动返回不带password的结果。
方法3:修正post save中间件
如果一定要用中间件处理,要直接操作文档存原始数据的内部属性_doc,而不是直接删doc上的属性:
UserSchema.post('save', function(doc){ delete doc._doc.password; });
注意这个方法只对save/create触发的文档生效,查询场景返回的结果还是会带password,覆盖范围不如方法2全。
内容的提问来源于stack exchange,提问作者lpares12
相关产品推荐
相关产品推荐

