如何在Express中以MongoDB的_id为参数实现按钮重定向并解决更新报错
解决MongoDB _id更新数据时的路由与类型转换错误
尝试通过MongoDB的_id字段更新数据时,直接访问更新链接(如http://localhost:3000/update/644a6d4c6fbe854da2375c61)正常,但点击按钮操作时出现以下两类错误:
Cannot GET /update
控制台报错:
CastError: Cast to ObjectId failed for value ":_id" (type string) at path "_id" for model "Post" and BSONError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
以下是当前代码及修复方案:
当前代码片段
1. 触发更新的HTML按钮代码
<form action="/update/:_id" method="get" id="edit-button"> <button class="btn btn-success" type="submit" id="edit-button"> Edit Post </button> </form>
2. Express服务器app.js代码
app.get('/update/:_id', function (req, res) { const updateId = req.params._id; Post.findOne({ _id: updateId }) .then((Posts) => { res.render('update', { updatedTitle: Posts.title, updatedContent: Posts.content, id: updateId, }); }) .catch((err) => { console.log(err); }); }); app.post('/update', function (req, res) { // const updateId = req.params.updateId; const updatedTitle = req.body.updatedTitle; const updatedContent = req.body.updatedContent; const updateId = req.body.id; post .findByIdAndUpdate( { _id: updateId }, { title: updatedTitle, content: updatedContent, } ) .then(() => res.redirect('/')); });
3. update.ejs视图模板代码
<form action="/update" method="get"> <div class="mb-3"> <label for="titleInput" class="form-label">Title</label> <input type="text" class="form-control" name="updatedTitle" value="<%= updatedTitle %>" required /> </div> <div class="mb-3"> <label for="postArea" class="form-label">Post</label> <textarea class="form-control" rows="5" name="updatedPost" value="<%= updatedContent %>" required ><%= updatedContent %></textarea> </div> <button class="btn btn-primary update" type="submit" name="id" value="<%= id %>" > Update </button> </form>
问题分析与修复步骤
1. 修复HTML表单的动态路由参数
第一个表单的action="/update/:_id"是硬编码的占位符,浏览器会直接将:_id作为字符串发送,导致服务器收到无效的_id值。
修复:在渲染列表页时,动态填充帖子的实际_id到action路径:
<!-- 假设列表页循环中每个帖子对象为post --> <form action="/update/<%= post._id %>" method="get" class="edit-form"> <button class="btn btn-success" type="submit">Edit Post</button> </form>
2. 修正表单请求方法与字段名不匹配
update.ejs中表单使用method="get",但服务器更新接口是app.post('/update'),导致GET请求找不到对应路由;同时textarea的name="updatedPost"与服务器中获取的updatedContent不匹配,会丢失内容。
修复:修改表单方法为post,修正字段名并改用隐藏域传递_id:
<form action="/update" method="post"> <input type="hidden" name="id" value="<%= id %>" /> <div class="mb-3"> <label for="titleInput" class="form-label">Title</label> <input type="text" class="form-control" name="updatedTitle" value="<%= updatedTitle %>" required /> </div> <div class="mb-3"> <label for="postArea" class="form-label">Post</label> <textarea class="form-control" rows="5" name="updatedContent" required ><%= updatedContent %></textarea> </div> <button class="btn btn-primary update" type="submit"> Update </button> </form>
3. 统一服务器代码中的模型名与优化查询
服务器POST接口中使用了小写post,但模型实际是大写Post;同时findByIdAndUpdate可以直接传入ID字符串,无需包裹对象。
修复:
app.post('/update', function (req, res) { const updatedTitle = req.body.updatedTitle; const updatedContent = req.body.updatedContent; const updateId = req.body.id; Post.findByIdAndUpdate( updateId, { title: updatedTitle, content: updatedContent }, { new: true } // 可选:返回更新后的文档 ) .then(() => res.redirect('/')) .catch(err => { console.error(err); res.status(500).send('更新失败'); }); });
4. 增强错误处理
在GET接口中添加帖子不存在的判断,避免渲染出错:
app.get('/update/:_id', function (req, res) { const updateId = req.params._id; Post.findOne({ _id: updateId }) .then((post) => { if (!post) { return res.status(404).send('帖子不存在'); } res.render('update', { updatedTitle: post.title, updatedContent: post.content, id: updateId, }); }) .catch((err) => { console.error(err); res.status(500).send('加载失败'); }); });
内容的提问来源于stack exchange,提问作者hypryyn
相关产品推荐
相关产品推荐

