You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:13:07