更新学生数据触发registrationNumber重复键报错且未修改该字段如何解决
报错原因及解决方案
核心问题
你遇到的duplicatekey: registrationNumber唯一键冲突报错由两个代码错误共同导致:
- findOneAndUpdate方法参数使用错误:Mongoose中该方法第一个参数必须为查询条件对象,你直接传入了
registrationNumber的字符串值,Mongoose会将其错误识别为_id字段进行匹配,匹配不到对应文档时就会尝试写入新文档,新文档的registrationNumber和已有记录重复就触发了唯一键校验报错。 - 未过滤更新字段:你直接全量展开
req.body作为更新内容,即使你没有主动修改registrationNumber字段,只要前端提交的表单中包含该字段(比如隐藏表单域),也会触发唯一键校验,同时存在敏感字段被恶意篡改的风险。
修复代码
router.get('/edit', isLoggedIn, async(req, res) => { const registrationNumber = req.user.username const student = await Student.findOne({registrationNumber}) res.render('students/edit', { student }) }) router.put('/edit', isLoggedIn, async(req, res) => { try { const registrationNumber = req.user.username // 方式1:手动提取允许更新的字段,安全性最高 const { name, grade, major /* 替换为你实际允许用户修改的字段 */ } = req.body const updateData = { name, grade, major } // 方式2:如果要保留前端提交的除registrationNumber外的所有字段,可直接解构排除 // const { registrationNumber: _ignore, ...updateData } = req.body const student = await Student.findOneAndUpdate( // 修正查询条件,按registrationNumber匹配对应学生 { registrationNumber }, updateData, // 新增配置:返回更新后的文档 + 触发字段合法性校验 { new: true, runValidators: true } ) res.redirect('/students/profile') } catch(e) { console.log(e) } })
内容的提问来源于stack exchange,提问作者Jajatee Nandinee Sahoo
相关产品推荐
相关产品推荐

