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

基于Prisma与MongoDB,如何避免重复创建点赞记录?

如何在Prisma + MongoDB中避免创建重复的点赞记录?

你可以通过在数据库层面添加复合唯一约束来解决这个问题,这比预先查询再创建的方式更高效,还能避免并发场景下的竞态条件。

步骤1:修改Prisma模型,添加复合唯一约束

在Like模型中,给userId和artworkId组合添加唯一约束,同时建议将这两个字段设为必填(因为点赞操作必然关联用户和作品):

model Like {
  id String @id @default(auto()) @map("_id") @db.ObjectId

  userId String @db.ObjectId
  user   User   @relation(fields: [userId], references: [id])

  artwork   Artwork @relation(fields: [artworkId], references: [id])
  artworkId String  @db.ObjectId

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  // 核心:设置复合唯一约束,确保同一用户不能重复点赞同一作品
  @@unique([userId, artworkId])
}

步骤2:执行Prisma迁移

修改模型后,运行以下命令将约束同步到MongoDB:

npx prisma migrate dev

注意:如果现有Like集合中已经存在重复的userId+artworkId记录,迁移会失败,需要先清理这些重复数据。

步骤3:业务代码中处理约束冲突

当尝试插入重复记录时,MongoDB会抛出重复键错误,Prisma会将其封装为P2002错误码,你可以在代码中捕获并处理:

async function addLike(userId, artworkId) {
  try {
    await prisma.like.create({
      data: {
        userId,
        artworkId
      }
    });
    return { success: true, msg: "点赞成功" };
  } catch (err) {
    // 捕获唯一约束冲突错误
    if (err.code === "P2002") {
      return { success: false, msg: "你已经点过赞了" };
    }
    // 其他错误正常抛出
    throw err;
  }
}

为什么这比预查询更优?

  • 减少数据库交互:省去了预先查询是否存在的步骤,只需要一次插入操作。
  • 避免竞态条件:如果用“先查询再插入”,高并发场景下可能出现两个请求同时查询到无记录,然后都插入重复数据的情况;而数据库层面的约束是原子性的,能彻底避免这个问题。
  • 性能更高:数据库的唯一索引是高效的,插入时的冲突检查比额外的查询更轻量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:15:27