首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用GraphQL查询中的字段来使用Prisma执行嵌套读取?

如何使用GraphQL查询中的字段来使用Prisma执行嵌套读取?
EN

Stack Overflow用户
提问于 2022-03-28 16:41:20
回答 1查看 575关注 0票数 1

我正在使用Prisma实现一个GraphQL接口,以公开存储在PostgreSQL数据库中的一些数据。我的代码是受GraphQL工具(SDL-first)示例启发的。但是,这个逻辑效率很低,我想改进它。

下面是一段很小的代码,用于显示问题并要求解决方案。我的真正代码当然更复杂。

我的GraphQL模式

代码语言:javascript
运行
复制
type Query {
  allUsers: [User!]!
}
type User {
  name: String!
  posts: [Post!]!
}
type Post {
  text: String!
  author: User!
}

我的解析器对象,在Node.JS代码中

代码语言:javascript
运行
复制
const resolvers = {
  Query: {
    allUsers: ()=>prisma.users.findMany()
  },
  User: {
    posts: (user)=>prisma.posts.findMany({where:{author:user.id}})
  }
};

问题

这段代码可以工作,但效率很低。假设您正在运行查询{allUsers{posts{text}}}

  1. 我的代码对N+1运行PostgreSQL查询,以获取整个结果:一个用于获取用户列表,另一个用于每个用户。使用JOIN的单个查询就足够了。
  2. 我的代码从它查询的每个表中选择每一列,即使我只需要user.id,而不需要user.name或其他任何东西。

问题

我知道Prisma支持(备选办法),它可以解决这两个问题。但是,我不知道如何使用GraphQL查询配置options对象。

如何从GraphQL查询中提取请求的字段列表?我如何使用这些来创建to options对象来使用Prisma执行最优的嵌套搜索?

EN

回答 1

Stack Overflow用户

发布于 2022-06-08 20:19:30

这个包可以帮助您解析请求信息:https://www.npmjs.com/package/graphql-parse-resolve-info

然后,您需要将其转换为可以在ORM中使用的可用参数。

下面是NestJS的一个示例:

代码语言:javascript
运行
复制
import {createParamDecorator, ExecutionContext} from '@nestjs/common';
import {GqlExecutionContext} from '@nestjs/graphql';
import {GraphQLResolveInfo} from 'graphql';
import {parseResolveInfo, ResolveTree} from 'graphql-parse-resolve-info';

export type PrismaSelect = {
  select: {
    [key: string]: true | PrismaSelect;
  };
};

export const Relations = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const info = GqlExecutionContext.create(ctx).getInfo<GraphQLResolveInfo>();
    const ast = parseResolveInfo(info);
    return astToPrisma(Object.values((ast as ResolveTree).fieldsByTypeName)[0]);
  },
);

export const astToPrisma = (ast: {
  [str: string]: ResolveTree;
}): PrismaSelect => {
  return {
    select: Object.fromEntries(
      Object.values(ast).map(field => [
        field.name,
        Object.keys(field.fieldsByTypeName).length === 0
          ? true
          : astToPrisma(Object.values(field.fieldsByTypeName)[0]),
      ]),
    ),
  };
};

那你就做:

代码语言:javascript
运行
复制
import {Parent, Query, ResolveField, Resolver} from '@nestjs/graphql';
import {PrismaService} from '../services/prisma.service';
import {User} from '../entities/user.entity';
import {Relations} from 'src/decorators/relations.decorator';
import {Prisma} from '@prisma/client';

@Resolver(() => User)
export class UserResolver {
  constructor(public prisma: PrismaService) {}
  @Query(() => [User])
  async usersWithRelationsResolver(
    @Relations() relations: {select: Prisma.UserSelect},
  ): Promise<Partial<User>[]> {
    return this.prisma.user.findMany({
      ...relations,
    });
  }

或者,如果您想解决N+1问题,可以使用Prisma内置findUnique方法。请参阅https://www.prisma.io/docs/guides/performance-and-optimization/query-optimization-performance#solving-the-n1-problem

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71650767

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档