如何在prisma.user.update中更新显式多对多关联的用户皮肤问题数据
报错原因
你当前用的是显式多对多建模,User 模型的 skinConcerns 字段直接关联的是中间表 SkinConcernsForUsers,而非 SkinConcern 表,你之前的写法是隐式多对多的用法,类型不匹配才会报错。
方案1:保持现有schema,直接在prisma.user.update中完成更新
不需要单独操作中间表,你可以在同一个更新请求里先删除该用户所有旧关联,再创建新关联,操作是原子性的,不会有并发问题:
// 假设本次提交的皮肤问题数组为 inputSkinConcerns const inputSkinConcerns = ["PIGMENTATION", "REDNESS"] await prisma.user.update({ where: { nickname }, data: { // 其他用户字段更新逻辑... skinConcerns: { // 删除当前用户所有旧的皮肤问题关联 deleteMany: {}, // 新建本次提交的关联 create: inputSkinConcerns.map(name => ({ skinConcern: { connect: { name } } })) } } })
如果提交的数组可能为空,也无需额外兼容,当数组为空时会直接删除所有关联,符合复选框全不选的业务逻辑。
方案2:直接操作中间表实现更新
如果不想删除旧关联再重建,要做增量更新,逻辑确实是先删除不在提交数组中的关联,再新增不存在的关联,可以用事务保证操作原子性:
const inputSkinConcerns = ["PIGMENTATION", "REDNESS"] // 先获取当前用户id const currentUser = await prisma.user.findUnique({ where: { nickname }, select: { id: true } }) const userId = currentUser.id // 查询本次提交的皮肤问题对应的id const targetConcerns = await prisma.skinConcern.findMany({ where: { name: { in: inputSkinConcerns } }, select: { id: true } }) const targetConcernIds = targetConcerns.map(item => item.id) await prisma.$transaction([ // 删除该用户不在本次提交列表里的关联 prisma.skinConcernsForUsers.deleteMany({ where: { userId, skinConcernId: { notIn: targetConcernIds } } }), // 批量创建新关联,跳过已存在的关联避免报错 prisma.skinConcernsForUsers.createMany({ data: targetConcernIds.map(concernId => ({ userId, skinConcernId: concernId })), skipDuplicates: true }) ])
这个方案不需要删除原有有效关联,适合关联数据量较大的场景。
可选优化:改用隐式多对多简化操作
如果你的中间表SkinConcernsForUsers不需要存储除了关联关系之外的额外字段,完全可以改用Prisma的隐式多对多建模,无需手动定义中间表,操作更简单:
model User { id String @id @default(cuid()) name String? nickname String? @unique // 其他字段... skinConcerns SkinConcern[] @relation("UserSkinConcerns") } model SkinConcern { id Int @id @default(autoincrement()) name String @unique users User[] @relation("UserSkinConcerns") }
改完schema后,你最开始写的set写法就可以直接用了:
await prisma.user.update({ where: { nickname }, data: { skinConcerns: { set: inputSkinConcerns.map(name => ({ name })) } } })
Prisma会自动维护中间表的增删逻辑,不需要手动处理。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

