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

如何在Prisma中按类型统计各帖子的Reaction数量?

解决方案:用Prisma或原生SQL实现帖子反应统计

你既可以用Prisma实现需求,也可以直接使用原生PostgreSQL SQL,两种方式都能高效完成统计,无需拉取大量Reaction记录。

方式一:用Prisma ORM实现

如果你的反应类型是固定的(比如只有like、thumbsup),可以利用Prisma的关联查询和聚合计数功能,直接在findMany中定义各类型的统计字段,类型安全且代码简洁。

Prisma Schema 示例

首先确保你的schema定义了正确的关联关系:

model Post {
  id        Int         @id @default(autoincrement())
  title     String
  reactions Reaction[]
}

model Reaction {
  id           Int           @id @default(autoincrement())
  userId       Int
  postId       Int
  reactionType ReactionType
  post         Post          @relation(fields: [postId], references: [id])

  @@unique([userId, postId, reactionType]) // 避免同一用户对同一帖子重复添加同类型反应
}

enum ReactionType {
  like
  thumbsup
  // 可添加其他反应类型
}

查询代码

const postsWithStats = await prisma.post.findMany({
  select: {
    id: true,
    title: true,
    // 统计like类型的数量
    likeCount: {
      _count: {
        where: { reactionType: 'like' }
      }
    },
    // 统计thumbsup类型的数量
    thumbsupCount: {
      _count: {
        where: { reactionType: 'thumbsup' }
      }
    },
    // 其他反应类型的统计同理添加
  },
});

查询结果中,没有对应反应的帖子会返回0作为计数。

方式二:用原生PostgreSQL SQL实现

如果你的反应类型是动态的(后续可能新增类型),或者需要更灵活的统计格式,直接用原生SQL会更高效。你可以通过CASE语句拆分各类型计数,或者用JSON函数将统计结果打包成对象。

固定类型统计SQL

SELECT 
  p.id,
  p.title,
  COALESCE(SUM(CASE WHEN r.reactionType = 'like' THEN 1 ELSE 0 END), 0) AS like_count,
  COALESCE(SUM(CASE WHEN r.reactionType = 'thumbsup' THEN 1 ELSE 0 END), 0) AS thumbsup_count
FROM "Post" p
LEFT JOIN "Reaction" r ON p.id = r."postId"
GROUP BY p.id, p.title;

动态类型统计(返回JSON)

如果要自动适配所有存在的反应类型,用json_object_agg将统计结果转为JSON对象:

SELECT 
  p.id,
  p.title,
  COALESCE(
    json_object_agg(r.reactionType, COUNT(r.id)),
    '{}'::json
  ) AS reaction_counts
FROM "Post" p
LEFT JOIN "Reaction" r ON p.id = r."postId"
GROUP BY p.id, p.title;

这个查询会返回一个reaction_counts字段,格式类似{"like":3,"thumbsup":1},无反应的帖子返回空对象{}。

在Prisma中执行原生SQL

你可以通过Prisma的$queryRaw方法直接执行上述SQL:

const postsWithStats = await prisma.$queryRaw`
  SELECT 
    p.id,
    p.title,
    COALESCE(json_object_agg(r.reactionType, COUNT(r.id)), '{}'::json) AS reaction_counts
  FROM "Post" p
  LEFT JOIN "Reaction" r ON p.id = r."postId"
  GROUP BY p.id, p.title;
`;

总结

  • 若反应类型固定,优先用Prisma的关联聚合查询,类型安全且符合ORM开发习惯;
  • 若反应类型动态或需要灵活格式,用原生SQL(可通过Prisma执行)更合适,性能也更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:05:30