如何基于Prisma的Post模型查询所有帖子的平均点赞数?
问题原因
你没法直接用aggregate查询平均点赞数,是因为likedBy是多对多关系字段,Prisma的aggregate方法目前仅支持对模型的标量字段(比如你代码里的views这种直接存储在Post表的字段)做聚合运算,不能直接对关系字段的计数做聚合,这也是你在生成的类型提示里找不到对应选项的原因。
解决方案
这里提供两种常用实现方式:
方案1:新增冗余标量字段(生产环境推荐,性能最优)
这是项目中最常用的方案,只需要给Post模型加一个likesCount标量字段存储点赞数即可:
model Post { // 原有字段保持不变 likesCount Int @default(0) // 新增冗余字段,存储当前帖子的点赞总数 likedBy UserProfile[] }
之后处理点赞/取消点赞逻辑时,同步原子更新这个likesCount字段即可,点赞逻辑示例:
// 点赞操作:同时关联点赞用户、更新点赞数 await prisma.post.update({ where: { id: postId }, data: { likedBy: { connect: { id: userId } }, likesCount: { increment: 1 } } })
后续查询平均点赞数的逻辑就和查询平均浏览量完全一致:
let queryAvgLikes = async () => { let query = await prisma.post.aggregate({ _avg: { likesCount: true } }) return query._avg.likesCount }
方案2:不修改模型,直接查询计算
如果不想新增冗余字段,也可以先查询所有帖子的点赞数,再手动计算平均值:
let queryAvgLikes = async () => { // 先批量查询所有帖子的点赞数 const postsWithLikeCount = await prisma.post.findMany({ select: { _count: { select: { likedBy: true } } } }) if (postsWithLikeCount.length === 0) return 0 // 求和后除以帖子总数得到平均值 const totalLikes = postsWithLikeCount.reduce((sum, post) => sum + post._count.likedBy, 0) return totalLikes / postsWithLikeCount.length }
如果数据量较大,上面的方法会有性能损耗,可以用原始SQL查询提升效率,以PostgreSQL为例:
const result = await prisma.$queryRaw` SELECT AVG(like_count) as avg_likes FROM ( SELECT COUNT("likedByUserId") as like_count FROM "_PostToUserProfile" GROUP BY "postId" ) as post_likes ` return result[0].avg_likes
注意:原始SQL中的多对多中间表名需要和Prisma自动生成的表名保持一致,如果你自定义了多对多中间表,替换为对应的表名即可。
内容的提问来源于stack exchange,提问作者TheHackerCoding
相关产品推荐
相关产品推荐

