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

Prisma关联查询问题:如何正确获取菜谱的关联评论?

解决菜谱评论查询的两个问题

问题根源

  1. Promise未等待完成:你用map遍历生成的是一堆Promise对象,直接返回的时候这些Promise还没执行完,所以拿到的都是pending状态,自然没有数据。
  2. 重复响应错误:如果之前用.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:03:36