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

Node.js Express+MongoDB MVC模型添加更新功能后报错排查

排查Node.js Express + MongoDB MVC应用更新文章后post.author.name未定义错误

错误详情

TypeError: C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\admin\posts-list.ejs:19
    17|       <ol id="posts-list">
    18|         <% for (const post of posts) { %>
 >> 19|         <li><%- include('includes/post-item', { post: post }) %></li>
    20|         <% } %>
    21|       </ol>
    22|       <% } %>

C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\admin\includes\post-item.ejs:3
    1| <article class="post-item">
    2|   <h2><%= post.title %></h2>
 >> 3|   <p class="post-item-author">Rédigé par <%= post.author.name %></p>
    4|   <p><%= post.summary %></p>
    5|   <div class="post-actions">
    6|     <form action="/blog/<%= post._id %>/delete" method="POST">

Cannot read properties of undefined (reading 'name')
    at eval ("C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\admin\includes\post-item.ejs":15:38)
    at post-item (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:703:17)
    at include (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:701:39)
    at eval ("C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\admin\posts-list.ejs":29:17)
    at posts-list (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:703:17)
    at tryHandleCache (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:274:36)
    at View.exports.renderFile [as engine] (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:491:10)
    at View.render (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\view.js:135:8)
    at tryRender (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\application.js:657:10)
    at Function.render (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\application.js:609:3) {
  path: 'C:\\Users\\DELL\\Desktop\\node-com4muz-database-mvc\\views\\admin\\posts-list.ejs'
}

问题根源分析

1. Post实例创建时参数顺序完全错误

在修改后的routes/admin/blog.js的POST /blog/:id/edit路由中,创建Post实例的参数传递顺序与构造函数定义不匹配:

// 路由中的错误调用
const post = new Post(
  enteredTitle,
  enteredSummary,
  enteredContent,
  req.params.id
);

而models/post.js中Post类的构造函数参数顺序为:

constructor(title, summary, content, date, author, image, id)

这里把req.params.id传到了**第四个参数(date)**的位置,第七个参数(id)实际为undefined。导致:

  • this.id无法被赋值(构造函数中仅当第七个参数id存在时才会设置)
  • save()方法会进入新增post的分支(而非更新分支),插入一个缺少author、date等关键字段的新post
  • 这个新增的post没有author字段,渲染列表时访问post.author.name就会触发undefined错误

2. Post模型save方法存在多处语法错误

在修改后的models/post.js的save()方法的更新分支中:

  • 未定义变量postId:查询条件使用{ _id: postId },但postId从未声明,应改为this.id
  • 字段赋值错误:$set中错误地将title设为this.id(ObjectId类型),实际应为this.title
  • 更新逻辑不完整:未保留原post的author、date、imagePath等字段(虽然$set不会删除原有字段,但参数传递错误导致进入新增分支,根本没执行更新)

修复方案

步骤1:修正路由中Post实例的参数传递

在routes/admin/blog.js的POST /blog/:id/edit路由中,按照构造函数顺序传递参数,仅传入需要更新的字段和id,其余参数可设为undefined:

router.post('/blog/:id/edit', async function (req, res) {
  const enteredTitle = req.body.title;
  const enteredSummary = req.body.summary;
  const enteredContent = req.body.content;

  // 按照构造函数顺序传递参数:title, summary, content, date, author, image, id
  const post = new Post(
    enteredTitle,
    enteredSummary,
    enteredContent,
    undefined, // date 保持原字段,无需传递
    undefined, // author 保持原字段,无需传递
    undefined, // image 保持原字段,无需传递
    req.params.id // 第七个参数才是id
  );
  await post.save();

  res.redirect('/posts');
});

步骤2:修复Post模型save方法的更新逻辑

在models/post.js中修正save()方法的错误:

async save() {
  let result;
  if (this.id) {
    // 修正查询条件和字段赋值
    result = await db
      .getDb()
      .collection('posts')
      .updateOne(
        { _id: this.id }, // 使用实例的this.id而非未定义的postId
        {
          $set: {
            title: this.title, // 修正为this.title而非this.id
            summary: this.summary,
            content: this.content
            // 如需更新日期可取消注释:date: new Date()
          }
        }
      );
  } else {
    result = await db.getDb().collection('posts').insertOne({
      title: this.title,
      summary: this.summary,
      content: this.content,
      date: this.date,
      author: this.author,
      imagePath: this.image
    });
  }

  return result;
}

步骤3:可选优化(确保更新时获取原post完整信息)

如果需要在更新时验证或修改其他字段,建议先从数据库获取原post的完整数据,再覆盖需要更新的内容:

router.post('/blog/:id/edit', async function (req, res) {
  const postId = new ObjectId(req.params.id);
  // 获取原post的完整数据
  const originalPost = await db.getDb().collection('posts').findOne({ _id: postId });
  
  if (!originalPost) {
    return res.status(404).render('404');
  }

  const enteredTitle = req.body.title;
  const enteredSummary = req.body.summary;
  const enteredContent = req.body.content;

  // 使用原post的date、author、image字段,仅更新需要修改的内容
  const post = new Post(
    enteredTitle,
    enteredSummary,
    enteredContent,
    originalPost.date,
    originalPost.author,
    originalPost.imagePath,
    req.params.id
  );
  await post.save();

  res.redirect('/posts');
});

内容的提问来源于stack exchange,提问作者Sofiane R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:20:28