在Prisma中为Post查询结果添加isLiked字段及类型存储咨询
问题描述
我存在User与Post的隐式多对多关系:用户可点赞多篇帖子,帖子可被多个用户点赞。对应的Prisma Schema如下:
model User { id String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid posts Post[] @relation("author") likes Post[] @relation("like") @@map("users") } model Post { id String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid author User @relation("author", fields: [author_id], references: [id]) author_id String @db.Uuid comments Comment[] likedBy User[] @relation("like") @@map("posts") }
现在需要查询帖子列表用于渲染,每个帖子需显示当前用户是否已点赞的状态,如何通过一次查询得到Post & { isLiked: boolean }结构?此外,由于该类型并非来自Prisma,遵循单一数据源原则,应将其存储在何处?
解决方案
一、一次查询获取带点赞状态的帖子列表
可以利用Prisma的查询API结合SQL的exists逻辑,在单次查询中直接计算出每个帖子的isLiked状态,有两种实现方式:
方式1:使用Prisma的$expr语法
const currentUserId = "当前用户的UUID"; // 替换为实际当前用户ID const posts = await prisma.post.findMany({ select: { id: true, author_id: true, author: { select: { id: true /* 按需添加作者字段 */ } }, // 其他需要的Post字段 isLiked: { $expr: { $exists: prisma.user.findFirst({ where: { id: currentUserId, likes: { some: { id: { $eq: prisma.post.id } } } } }) } } } });
方式2:使用原生SQL片段(性能更优)
隐式多对多关系会自动生成中间表(默认命名为users_likes_posts,可通过Prisma配置自定义),直接通过SQL判断当前用户是否在帖子的点赞列表中:
const currentUserId = "当前用户的UUID"; const posts = await prisma.post.findMany({ select: { id: true, author_id: true, author: true, // 其他需要的Post字段 isLiked: { sql: `EXISTS (SELECT 1 FROM users_likes_posts WHERE "userId" = '${currentUserId}' AND "postId" = "Post"."id")` } } });
两种方式返回的结果都会包含Post的所有选中字段以及isLiked布尔值,完全符合Post & { isLiked: boolean }的结构要求。
二、自定义类型的存储位置
遵循单一数据源原则,建议将这个自定义类型:
- 放在Prisma Schema所在目录的类型声明文件中,比如
prisma/post-types.ts,和Prisma自动生成的类型(@prisma/client导出)保持相近,便于统一维护。 - 类型声明示例:
import { Post } from "@prisma/client"; export type PostWithLikeStatus = Post & { isLiked: boolean; };
后续业务代码中直接导入该类型即可,避免重复定义,确保类型的单一性。
内容的提问来源于stack exchange,提问作者Arc
相关产品推荐
相关产品推荐

