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

Express JS项目双表插入及重复电影数据校验实现问题

解决方案:Express + PostgreSQL 影评博客双表入库实现

核心需求

  • 在POST /submit请求中完成movie和post表的联动插入
  • 检查电影是否已存在,存在则终止提交流程
  • 加入异常处理,保障数据一致性

完整代码实现

app.post("/submit", async (req, res) => {
  const postTitle = req.body.titlepost;
  const articles = req.body.articles;
  const rating = req.body.rating;
  
  // 取最近获取的有效电影数据(假设每次提交对应最后一条拉取结果)
  const movieData = fetchResult[fetchResult.length - 1];
  if (!movieData || movieData.title === "Please fetch some data") {
    return res.status(400).send("请先获取有效的电影数据");
  }

  let client;
  try {
    client = await pool.connect();
    // 开启事务,确保双表操作原子性
    await client.query("BEGIN");

    // 1. 检查电影是否已存在(用title+year做唯一校验,可替换为IMDB ID提升精准度)
    const checkMovieSql = `SELECT id FROM movie WHERE title = $1 AND year = $2`;
    const checkResult = await client.query(checkMovieSql, [movieData.title, movieData.year]);
    
    if (checkResult.rows.length > 0) {
      await client.query("ROLLBACK");
      return res.status(400).send("该电影数据已存在,无法重复提交影评");
    }

    // 2. 插入movie表并返回自增主键
    const insertMovieSql = `
      INSERT INTO movie (title, year, genre, director, image)
      VALUES ($1, $2, $3, $4, $5)
      RETURNING id
    `;
    const movieResult = await client.query(insertMovieSql, [
      movieData.title,
      movieData.year,
      movieData.genre,
      movieData.director,
      movieData.image
    ]);
    const movieId = movieResult.rows[0].id;

    // 3. 插入post表,关联movie_id外键
    const insertPostSql = `
      INSERT INTO post (title, content, rating, movie_id)
      VALUES ($1, $2, $3, $4)
    `;
    await client.query(insertPostSql, [postTitle, articles, rating, movieId]);

    // 提交事务
    await client.query("COMMIT");
    // 重置缓存数组,避免重复提交
    fetchResult = [{ title: "Please fetch some data", image: "/images/nodata.png" }];
    res.redirect("/"); // 提交成功后跳转至首页或影评列表页

  } catch (error) {
    // 异常时回滚事务
    if (client) await client.query("ROLLBACK");
    console.error("影评提交失败:", error);
    res.status(500).send("提交失败,请稍后重试");
  } finally {
    // 释放数据库连接
    if (client) client.release();
  }
});

关键逻辑说明

  • 事务原子性:通过BEGIN/COMMIT/ROLLBACK保证两张表的操作要么同时成功,要么同时回滚,避免出现单表数据残留的情况
  • 重复数据校验:通过电影标题+年份组合查询,判断数据是否已存在,可根据业务需求替换为IMDB ID等更唯一的标识
  • 外键关联实现:插入movie表时用RETURNING id获取生成的主键,以此作为post表movie_id的关联值
  • 连接资源管理:在finally块中释放数据库连接,防止连接池资源泄漏
  • 缓存重置:提交成功后重置fetchResult数组,避免用户重复提交同一电影的影评

内容的提问来源于stack exchange,提问作者Sandi Miftah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:07:18