bcryptjs在Mongoose的insertMany方法不生效,create方法运行正常如何解决?
问题描述
环境版本
- bcryptjs 版本:
"bcryptjs": "^2.4.3" - mongoose 版本:
"mongoose": "^6.0.12"
我需要在用户创建或密码更新时加密用户密码,使用 User.create() 创建单个用户时一切运行正常,密码成功加密;但使用 User.insertMany() 时数据虽然插入成功,密码却没有被加密。
我的 Schema 定义如下:
const userSchema = mongoose.Schema( { name: { type: String, required: true }, surname: { type: String, required: true }, voterId: { type: String, required: true, unique: true }, password: { type: String, required: true, unique: true, }, votedFor: [ { type: mongoose.Schema.ObjectId, ref: 'Election' } ], finishedVoting: { type: Boolean, required: true, default: false }, isAdmin: { type: Boolean, required: true, default: false, }, }, { timestamps: true, } ) userSchema.pre('save', async function(next) { // 仅当密码被修改时执行该逻辑 if (!this.isModified('password')) return next(); // 用10轮盐值加密密码 this.password = await bcrypt.hash(this.password, 10); next(); });
我尝试插入的示例数据:
const voters = [ { name: "Sherali", surname: "Samandarov", voterId: "194199", password: "FA654644", // 预期会被加密 isAdmin: false, finishedVoting: false }, { name: "Sherali", surname: "Samandarov", voterId: "184183", password: "MB454644", // 预期会被加密 isAdmin: false, finishedVoting: false }, { name: "Sherali", surname: "Samandarov", voterId: "194324", password: "FA651684", // 预期会被加密 isAdmin: false, finishedVoting: false } ]
我猜测是 userSchema.pre('save', ...) 钩子在调用 insertMany() 时没有被触发。
解答
问题原因
你的猜测是正确的,Mongoose 默认配置下 insertMany 方法不会触发单个文档的 save 前置钩子,该方法是直接向 MongoDB 发送批量插入请求,不会逐一对每个文档执行保存前的钩子逻辑,因此你定义的密码加密逻辑没有运行。
解决方案
以下两种方案均可解决该问题,可根据实际场景选择:
方案一:新增 insertMany 前置钩子(推荐)
在现有 Schema 中新增批量插入的前置钩子,统一处理所有批量插入场景的密码加密:
userSchema.pre('insertMany', async function(next, docs) { // 遍历所有待插入的文档,逐个加密密码 for (const user of docs) { user.password = await bcrypt.hash(user.password, 10); } next(); });
新增该钩子后,所有调用 User.insertMany() 的场景都会自动加密密码,无需修改原有调用逻辑。
方案二:插入前手动批量加密密码
如果不想修改 Schema 定义,也可以在调用插入方法前提前处理好密码加密:
// 批量加密所有用户密码 const processedVoters = await Promise.all( voters.map(async (voter) => { voter.password = await bcrypt.hash(voter.password, 10); return voter; }) ); // 执行批量插入 await User.insertMany(processedVoters);
内容的提问来源于stack exchange,提问作者ABDULLOKH MUKHAMMADJONOV
相关产品推荐
相关产品推荐

