Prisma关联查询问题:如何正确获取菜谱的关联评论?
解决菜谱评论查询的两个问题
问题根源
- Promise未等待完成:你用
map遍历生成的是一堆Promise对象,直接返回的时候这些Promise还没执行完,所以拿到的都是pending状态,自然没有数据。 - 重复响应错误:如果之前用
.then()/.catch(),大概率是在某个分支里多次调用了res.json(),导致重复发送HTTP响应头,触发那个错误。
修复方案(基础版:修正Promise问题)
把map生成的Promise数组用Promise.all()包裹,等待所有查询完成后再返回:
const getRecipeComments = async (req, res) => { try { const recipe_id = Number(req.query.recipe_id); const commentRelations = await prisma.recipe_comments.findMany({ where: { recipe: { id: recipe_id } }, select: { comment_id: true } }); // 用Promise.all等待所有评论查询完成 const comments = await Promise.all( commentRelations.map(async (relation) => { // 单个评论用findUnique更合适(id唯一),比findMany高效 return await prisma.comment.findUnique({ where: { id: relation.comment_id } }); }) ); res.status(200).json({ success: true, message: "获取到所有菜谱评论!", comments }); } catch (error) { res.status(500).json({ success: false, message: "请重试!", error: error.message }); } };
最优方案:用Prisma关联查询(跳过中间表手动查询)
既然你已经有recipe_comments关联表,只要在Prisma Schema里正确定义了模型关联,就可以直接通过recipe查询关联的comment,不需要手动查中间表,代码更简洁高效:
假设你的Prisma Schema大概是这样:
model Recipe { id Int @id @default(autoincrement()) title String // 定义与评论的多对多关联,指定中间表 comments Comment[] @relation("RecipeComments", through: "recipe_comments") } model Comment { id Int @id @default(autoincrement()) content String // 反向关联 recipes Recipe[] @relation("RecipeComments", through: "recipe_comments") } model recipe_comments { recipe_id Int comment_id Int recipe Recipe @relation(fields: [recipe_id], references: [id]) comment Comment @relation(fields: [comment_id], references: [id]) @@id([recipe_id, comment_id]) }
那查询代码可以简化成:
const getRecipeComments = async (req, res) => { try { const recipe_id = Number(req.query.recipe_id); // 直接通过Recipe查询关联的comments const recipe = await prisma.recipe.findUnique({ where: { id: recipe_id }, include: { comments: true } // 包含关联的评论数据 }); if (!recipe) { return res.status(404).json({ success: false, message: "菜谱不存在!" }); } res.status(200).json({ success: true, message: "获取到所有菜谱评论!", comments: recipe.comments }); } catch (error) { res.status(500).json({ success: false, message: "请重试!", error: error.message }); } };
注意事项
- 用
findUnique替代findMany查询单个评论,因为评论ID是唯一的,findUnique性能更好。 - 关联查询是Prisma的优势之一,能避免N+1查询问题(原代码里循环查评论就是N+1,效率低)。
- 确保在catch块里只发送一次响应,不要在其他分支重复调用
res.json(),就能避免“Can't set headers after they are sent”错误。
内容的提问来源于stack exchange,提问作者Mushood Hanif
相关产品推荐
相关产品推荐

