Mongoose中.save()方法无法更新MongoDB数据库求助
问题描述
我在其他Schema里已经实现了数据更新功能(需要的话可以提供对应代码),但在User Schema里复现的时候,没办法更新MongoDB数据库。这个功能在其他Schema里运行正常,现在卡壳了,求帮忙!
相关代码
POST控制器
console.log("post"); const userId = req.body.userId; const updatedName = req.body.name; const updatedPassword = req.body.password; const updatedEmail = req.body.email; const updatedSkype = req.body.skype; const updatedDepartment = req.body.department; const updatedJobtitle = req.body.jobtitle; const updatedLinemanager = req.body.linemanager; const updatedNinumber = req.body.ninumber; // const updatedJoinDate = req.body.joindate; // console.log(req.body); User.findById(userId) .then((user) => { isadmin = user.isadmin; name = updatedName; password = updatedPassword; email = updatedEmail; skype = updatedSkype; department = updatedDepartment; jobtitle = updatedJobtitle; linemanager = updatedLinemanager; ninumber = updatedNinumber; joindate = user.joindate; return user.save(); }) .then((result) => { console.log("User EDITED!"); res.redirect("/staffdir"); }) .catch((err) => console.log(err)); };
User模型
const mongoose = require("mongoose"); const Schema = mongoose.Schema; const userSchema = new Schema({ isadmin: { type: Boolean, required: true, }, name: { type: String, required: true, }, password: { type: String, required: true, }, email: { type: String, required: true, }, skype: { type: String, required: true, }, department: { type: String, required: true, }, jobtitle: { type: String, required: true, }, linemanager: { type: String, required: true, }, ninumber: { type: String, required: true, }, joindate: { type: Date, required: true, }, }); module.exports = mongoose.model("User", userSchema);
路由
router.get("/add-user", adminController.getAddUser); router.get("/edit-user/:userId", adminController.getEditUser); router.get("/edit-user-list", adminController.getEditUserList); //POST USER router.post("/add-user", adminController.postAddUser); router.post("/edit-user/edit-user", adminController.postEditUser); router.post("/edit-user", adminController.postEditUser); router.post("/destroy-user", adminController.postDeleteUser);
HTML/EJS模板
<%- include('../includes/head.ejs') %> <link rel="stylesheet" href="/css/admin.css" /> <link rel="stylesheet" href="/css/add-user.css" /> <body> <img src="pozzani.png" alt="pozzani logo" class="pozzanilogo" /> <div class="mainbackground"> <div class="leftcolumn"> <%- include('../includes/signout.ejs') %> <%- include('../includes/nav.ejs') %> <%- include('../includes/useful.ejs') %> </div> <div class="admin-column"> <h2 class="importanttitle">EDIT USER</h2> <div class="update-container"> <h3 class="admin-title">Welcome to the USER edit tool</h3> <p class="admin-content">Please edit forms below to make change. <b>ALL EDITS ARE FINAL!</b></p> <form class="user-form" action="edit-user" method="POST"> <div class="form-section"> <label for="isadmin">Is Admin?</label> <select id="isadmin" name="isadmin"> <% if (!user.isadmin) { %> <option value="false" selected>False</option> <option value="false">False</option> <option value="false">False</option> <option value="false">False</option> <option value="false">False</option> <option value="false">False</option> <option value="true">True - ARE YOU SURE? USER WILL BE ABLE TO EDIT USERS AND UPDATES</option> <% } else { %> <option value="true" selected>True - ARE YOU SURE? USER WILL BE ABLE TO EDIT USERS AND UPDATES</option> <% } %> </select> </div> <div class="form-section"> <label for="name">Name</label> <input type="text" name="name" id="name" value="<%= user.name %>" > </div> <div class="form-section"> <label for="password">Password</label> <input type="text" name="password" id="password" value="<%= user.password %>"> </div> <div class="form-section"> <label for="email">Email</label> <input type="email" name="email" id="email" value="<%= user.email %>"> </div> <div class="form-section"> <label for="skype">Skype</label> <input type="text" name="skype" id="skype" value="<%= user.skype %>"> </div> <div class="form-section"> <label for="department">Department</label> <input type="text" name="department" id="department" value="<%= user.department %>"> </div> <div class="form-section"> <label for="jobtitle">Job Title</label> <input type="text" name="jobtitle" id="jobtitle" value="<%= user.jobtitle %>"> </div> <div class="form-section"> <label for="linemanager">Line Manager</label> <input type="text" name="linemanager" id="linemanager" value="<%= user.linemanager %>"> </div> <div class="form-section"> <label for="ninumber">National Insurance Number</label> <input type="text" name="ninumber" id="ninumber" value="<%= user.ninumber %>"> </div> <!-- <div class="form-section"> <label for="joindate">Join Date</label> <input type="date" name="joindate" id="joindate" value="<%= user.joindate %>"> </div> --> <input type="hidden" value="<%= user._id %>" name="userId"> <button class="admin-btn" type="submit"><% userId = user._id %>Edit User</button> </form> </div> </div> </div> </body> </html>
问题根源与修复方案
核心问题
你的POST控制器犯了关键错误:没有把更新值赋值给从数据库查询到的user对象,而是直接给未声明的全局变量赋值。这样user对象根本没被修改,调用user.save()自然不会更新数据库。此外还有几个潜在问题:
- 表单提交的
isadmin字段完全没被处理 - 变量未用
let/const声明,污染全局作用域 - 查询后再保存的操作冗余,可直接用更高效的更新方法
修复后的POST控制器代码
console.log("post"); const userId = req.body.userId; // 处理布尔值:表单提交的是字符串,需转成布尔类型 const updatedIsAdmin = req.body.isadmin === 'true'; const updatedName = req.body.name; const updatedPassword = req.body.password; const updatedEmail = req.body.email; const updatedSkype = req.body.skype; const updatedDepartment = req.body.department; const updatedJobtitle = req.body.jobtitle; const updatedLinemanager = req.body.linemanager; const updatedNinumber = req.body.ninumber; // 方法1:修正原逻辑,正确修改user对象 User.findById(userId) .then((user) => { // 直接修改查询到的user对象属性 user.isadmin = updatedIsAdmin; user.name = updatedName; user.password = updatedPassword; user.email = updatedEmail; user.skype = updatedSkype; user.department = updatedDepartment; user.jobtitle = updatedJobtitle; user.linemanager = updatedLinemanager; user.ninumber = updatedNinumber; // joindate保持原数值,无需修改 return user.save(); }) .then((result) => { console.log("User EDITED!"); res.redirect("/staffdir"); }) .catch((err) => { console.error(err); res.status(500).send('更新失败'); // 增加错误反馈,方便调试 }); // 方法2:更高效的findByIdAndUpdate(推荐) // User.findByIdAndUpdate( // userId, // { // isadmin: updatedIsAdmin, // name: updatedName, // password: updatedPassword, // email: updatedEmail, // skype: updatedSkype, // department: updatedDepartment, // jobtitle: updatedJobtitle, // linemanager: updatedLinemanager, // ninumber: updatedNinumber // }, // { new: true, runValidators: true } // 返回更新后的文档,运行Schema验证规则 // ) // .then((result) => { // console.log("User EDITED!"); // res.redirect("/staffdir"); // }) // .catch((err) => { // console.error(err); // res.status(500).send('更新失败'); // });
额外优化点
- 清理表单中重复的
isadmin选项:
<select id="isadmin" name="isadmin"> <% if (!user.isadmin) { %> <option value="false" selected>False</option> <option value="true">True - 确认操作?该用户将拥有编辑用户和数据的权限</option> <% } else { %> <option value="true" selected>True - 确认操作?该用户将拥有编辑用户和数据的权限</option> <option value="false">False</option> <% } %> </select>
- 密码字段改用
type="password",避免明文显示 - 控制器中所有变量用
const声明,避免全局作用域污染
内容的提问来源于stack exchange,提问作者bfrith
相关产品推荐
相关产品推荐

