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

Apollo Server 4+Prisma 5 用户与评论双向查询Resolver配置问题

问题描述

使用Apollo Server 4 + Prisma 5搭建电商项目,需要实现用户与评论的双向查询:

  • 查询用户时能获取其关联的评论
  • 评论作为顶层查询时能返回关联用户
    数据库中Comment通过user_id外键关联User,是一对多/多对一关系。

当前问题:

  • 查询用户时comments字段返回null,不想在ORM层用include做关联查询,希望通过Resolver的parent参数实现子字段懒加载
  • 运行时报错:Error: Comment.userComments defined in resolvers, but not in schema

相关代码如下:

Prisma模型

model User {
  id          String        @id @default(uuid())
  username    String        @unique
  email       String        @unique
  password    String
  first_name  String
  last_name   String?
  created_at  DateTime      @default(now())
  updated_at  DateTime      @updatedAt
  deleted     Boolean       @default(false)
  comments    Comment[]
  ratings     Rating[]
  orders      Order[]
  UserAddress UserAddress[]
}

model Comment {
  id         String        @id @default(uuid())
  user       User     @relation(fields: [user_id], references: [id])
  user_id    String   // Change type to String
  product    Product  @relation(fields: [product_id], references: [id])
  product_id String
  content    String
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
  deleted    Boolean  @default(false)
}

GraphQL Schema

type Query {
  "Get a user by their email"
  userByEmail(email: String): User!
}

"This type represents a user in the system"
type User {
  "Unique identifier for the user"
  id: ID!
  "Username for login"
  username: String!
  "User's email address"
  email: String!
  "User's first name"
  first_name: String!
  "User's last name (optional)"
  last_name: String!
  "List of comments authored by the user (optional)"
  comments: [Comment]
  "List of ratings created by the user (optional)"
  ratings: [Rating]
  "List of orders placed by the user (optional)"
  orders: [Order]
  "List of user's addresses"
  addresses: [Address]
}

type Comment {
  "Unique identifier for the comment"
  id: ID!
  "Content of the comment"
  content: String!
  "User who authored the comment"
  user: User
  "Product this comment is associated with"
  product: Product
}

当前Resolver代码

import { getUserByEmail, getCommentsByUserId } from '../../dataAccessLayer/orm/user';
import { User } from '../../generated/types';

export const resolvers = {
  Query: {
    userByEmail: async (_parent: unknown, { email }: { email: string }) => {
      console.log('parent', email);
      const user = await getUserByEmail(email); // Already includes comments
      return user;
    },
  },
  Comment: {
    userComments: (parent: User) => {
      console.log('parent', parent);
      const userId = parent.id;
      return getCommentsByUserId(userId);
    },
  },
};

ORM查询代码

import prisma from '../prismaClient';

export async function getUserByEmail(email: string) {
  return await prisma.user.findUnique({
    where: {
      email,
    },
  });
}

export async function getCommentsByUserId(id: string) {
  return await prisma.comment.findMany({
    where: {
      user_id: id,
    },
    include: {
      user: true, // Include user relation
    },
  });
}

解决方案

1. 修正Resolver的字段映射错误

报错原因是Resolver里定义了Comment.userComments,但你的GraphQL Schema中Comment类型并没有这个字段——实际是User类型有comments字段,Comment类型有user字段。调整Resolver结构如下:

import { getUserByEmail, getCommentsByUserId, getUserById } from '../../dataAccessLayer/orm/user';
import { Comment, User } from '../../generated/types';
import prisma from '../prismaClient';

export const resolvers = {
  Query: {
    userByEmail: async (_parent: unknown, { email }: { email: string }) => {
      // 仅查询用户基础数据,不提前关联评论
      return await getUserByEmail(email);
    },
    // 补充顶层评论查询,满足"评论作为顶层查询"的需求
    commentById: async (_parent: unknown, { id }: { id: string }) => {
      return await prisma.comment.findUnique({ where: { id } });
    },
  },
  // 实现User类型的comments字段Resolver,懒加载评论
  User: {
    comments: async (parent: User) => {
      // parent是上层查询返回的User对象,直接用其id查询关联评论
      return await getCommentsByUserId(parent.id);
    },
  },
  // 实现Comment类型的user字段Resolver,懒加载关联用户
  Comment: {
    user: async (parent: Comment) => {
      // parent是上层查询返回的Comment对象,用其user_id查询关联用户
      return await getUserById(parent.user_id);
    },
  },
};

2. 补充ORM层的查询函数

需要添加通过ID查询用户的函数,用于评论关联用户的查询:

import prisma from '../prismaClient';

export async function getUserByEmail(email: string) {
  return await prisma.user.findUnique({
    where: { email },
  });
}

export async function getUserById(id: string) {
  return await prisma.user.findUnique({
    where: { id },
  });
}

export async function getCommentsByUserId(id: string) {
  // 无需include user,因为Comment的user字段会由Resolver懒加载
  return await prisma.comment.findMany({
    where: { user_id: id },
  });
}

3. 验证查询效果

现在可以执行以下查询验证功能:

  • 查询用户及其评论:
query {
  userByEmail(email: "user@example.com") {
    id
    username
    comments {
      id
      content
    }
  }
}
  • 查询评论及其关联用户:
query {
  commentById(id: "comment-id-123") {
    id
    content
    user {
      id
      username
    }
  }
}

核心原理

  • 顶层查询仅返回基础数据,不做预关联查询
  • 子字段的Resolver通过parent参数获取上层对象的关联ID,按需发起数据库查询,实现懒加载,符合GraphQL按需获取数据的最佳实践
  • 避免了ORM层提前include带来的性能浪费,只查询客户端实际需要的数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:35:04