Next.js配合Prisma如何基于hash和user_id两个联合条件执行upsert操作
解决方案
核心原因:Prisma的upsert方法要求where参数必须传入唯一索引对应的字段/组合,你现在报错就是因为虽然业务上hash和user_id的组合是唯一的,但没有在Prisma Schema里显式声明这个联合唯一约束,所以Prisma没有生成对应的复合唯一查询类型。
两种可选方案如下:
方案1(推荐):显式声明联合唯一索引,直接用upsert
这个方案是原子操作,不会有并发问题,性能也更好。
- 修改你的
schema.prisma里的categories模型定义,添加联合唯一约束:
model categories { id Int @id @default(autoincrement()) hash String user_id Int name String // 新增这行,声明hash和user_id的组合是唯一的 @@unique([hash, user_id]) }
- 执行
prisma generate更新TS类型定义。 - 修改你的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
相关产品推荐
相关产品推荐

