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

Express JS PUT请求报错:重复Product Id问题求助

问题解决:Express+PostgreSQL购物车PUT请求报重复主键错误(23505)

问题描述

使用Express JS连接PostgreSQL开发电商商城,包含商品目录表和用户购物车表(user_product),购物车表设有product_quantity字段。需求为点击「加入购物车」按钮时:

  • 商品未在购物车:通过POST请求新增条目
  • 商品已在购物车:通过PUT请求更新数量

但点击同一商品第二次时,触发PUT请求却出现PostgreSQL重复主键错误(错误码23505),POST和DELETE功能正常。

报错信息

{
  length: 209,
  severity: 'ERROR',
  code: '23505',
  detail: 'Key (product_id)=(4) already exists.',
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: 'public',
  table: 'user_product',
  column: undefined,
  dataType: undefined,
  constraint: 'user_product_pkey',
  file: 'nbtinsert.c',
  line: '670',
  routine: '_bt_check_unique'
}

问题分析

  1. 客户端重复判断逻辑失效:checkIfRepeatedInCart函数中,用product.id与传入的product_id匹配,但购物车列表itemsAddedToCartList中存储的商品字段为product_id而非id,导致无法识别已存在的购物车商品,误触发POST请求而非PUT,引发重复主键冲突。
  2. 数量计算逻辑错误:当前代码用原商品的product_quantity(库存数量)加1作为新数量,而非购物车中该商品的当前数量,会导致更新结果不准确。

解决方案

1. 修正客户端重复判断函数

将字段匹配逻辑从product.id改为product.product_id,确保能正确识别购物车中已存在的商品:

const checkIfRepeatedInCart = (productId) => {
  return itemsAddedToCartList.find((product) => product.product_id === productId);
}

2. 修正PUT请求的数量计算逻辑

从购物车列表中获取目标商品的当前数量,再加1得到新数量,并更新本地购物车列表:

else {
  // 从本地购物车列表找到对应商品
  const cartItem = itemsAddedToCartList.find(item => item.product_id === product.product_id);
  const newQuantity = cartItem.product_quantity + 1;
  
  fetch(`http://localhost:5000/cart-products/${product.product_id}`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },    
    body: JSON.stringify({ product_quantity: newQuantity })
  })
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
    // 更新本地购物车列表的数量
    itemsAddedToCartList = itemsAddedToCartList.map(item => 
      item.product_id === product.product_id 
        ? {...item, product_quantity: newQuantity} 
        : item
    );
  })
  .catch((error) => console.error(error));
}

3. 可选:服务端原子更新优化(避免并发问题)

为防止并发场景下的数量更新错误,可将服务端的UPDATE语句改为数据库原子递增,无需客户端计算新数量:

app.put('/cart-products/:product_id', async (req,res) => {
  try {
    const { product_id } = req.params;
    // 数据库内直接递增数量,返回更新后的数据
    const updatedQuantity = await pool.query(
      "UPDATE user_product SET product_quantity = product_quantity + 1 WHERE product_id = $1 RETURNING *", 
      [product_id]
    );
    res.json(updatedQuantity.rows[0]);
  } catch (error) {
    console.log(error.message);
    res.status(500).json({error: error.message});
  }
})

对应客户端PUT请求可简化为:

fetch(`http://localhost:5000/cart-products/${product.product_id}`, {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' }
})

验证步骤

  1. 首次点击商品,确认POST请求成功插入购物车数据
  2. 再次点击同一商品,确认触发PUT请求而非POST
  3. 检查数据库中该商品的product_quantity是否正确递增

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:23:12