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

Next.js配合Prisma如何基于hash和user_id两个联合条件执行upsert操作

解决方案

核心原因:Prisma的upsert方法要求where参数必须传入唯一索引对应的字段/组合,你现在报错就是因为虽然业务上hash和user_id的组合是唯一的,但没有在Prisma Schema里显式声明这个联合唯一约束,所以Prisma没有生成对应的复合唯一查询类型。

两种可选方案如下:

方案1(推荐):显式声明联合唯一索引,直接用upsert

这个方案是原子操作,不会有并发问题,性能也更好。

  1. 修改你的schema.prisma里的categories模型定义,添加联合唯一约束:
model categories {
  id        Int    @id @default(autoincrement())
  hash      String
  user_id   Int
  name      String
  // 新增这行,声明hash和user_id的组合是唯一的
  @@unique([hash, user_id])
}
  1. 执行prisma generate更新TS类型定义。
  2. 修改你的upsert代码,where参数使用Prisma自动生成的复合唯一键,默认命名是两个字段名下划线拼接:
const category = await prisma.categories.upsert({
  where: {
    hash_user_id: {
      hash,
      user_id: id,
    }
  },
  update: {
    name,
  },
  create: {
    hash,
    name,
    user_id: id,
  },
});

提示:如果你在声明联合唯一时自定义了约束名,比如@@unique([hash, user_id], name: "unique_hash_user"),那where里的键名就用你自定义的名字即可。

方案2:手动实现upsert逻辑(不推荐,存在并发风险)

如果你暂时不方便修改Schema,可以手动先查询再判断执行操作,高并发场景下需要配合事务+联合唯一约束兜底,避免出现重复插入的问题:

// 开启事务保证操作一致性
const category = await prisma.$transaction(async (tx) => {
  // 先查询是否存在匹配记录
  const existCategory = await tx.categories.findFirst({
    where: {
      hash,
      user_id: id
    }
  });
  if (existCategory) {
    // 存在就更新
    return tx.categories.update({
      where: { id: existCategory.id },
      data: { name }
    });
  } else {
    // 不存在就创建
    return tx.categories.create({
      data: {
        hash,
        name,
        user_id: id
      }
    });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:06:04