在NestJS / GraphQL请求中获取请求的键的列表

时间:2019-10-25 01:13:03

标签: graphql nestjs

我只是想弄明白,所以我的类型不正确。

@Resolver()
export class ProductsResolver {
    @Query(() => [Product])
    async products() {
        return [{
            id: 55,
            name: 'Moonshine',
            storeSupplies: {
                London: 25,
                Berlin: 0,
                Monaco: 3,
            },
        }];
    }
}

如果我在查询以下请求数据

{
    products{
      id,
      name,
    }
}

我希望async carriers()收到['id', 'name']。我想跳过storeSupplies的获取,因为这可能是一个昂贵的SQL调用。


我是GraphQL的新手,我可能错过了一些显而易见的甚至整个模式。预先感谢。

2 个答案:

答案 0 :(得分:3)


基本上,您可以分隔StoreSupplies个查询,以确保在对产品进行查询时不会得到它们。
您还可以在解析器中获取请求的密钥,然后根据它们进行查询。为此,您可以定义一个参数修饰符,如下所示:

import { createParamDecorator } from '@nestjs/common';

export const Info = createParamDecorator(
  (data, [root, args, ctx, info]) => info,
);

然后像下面这样在解析器中使用它:

  @UseGuards(GqlAuthGuard)
  @Query(returns => UserType)
  async getMe(@CurrentUser() user: User, @Info() info): Promise<User> {
    console.log(
      info.fieldNodes[0].selectionSet.selections.map(item => item.name.value),
    );
    return user;
  }

例如,当您运行此查询时

{
  getMe{
    id
    email
    roles
  }
}

console.log的输出是:

[ 'id', 'email', 'roles' ]

答案 1 :(得分:3)

另一种选择是直接使用NestJS提供的@Info装饰器,如下所示:https://docs.nestjs.com/graphql/resolvers-map#decorators

它可能看起来像这样:

@Resolver()
export class ProductsResolver {
    @Query(() => [Product])
    async products(
    @Info() info
    ) {
        // Method 1 thanks to @pooya-haratian.
        // Update: use this method; read below article to understand why.
        let keys = info.fieldNodes[0].selectionSet.selections.map(item => item.name.value);
        // Method 2 by me, but I'm not sure which method is best.
        // Update: don't use this; read below article to understand why.
        let keys = info.operation.selectionSet.selections[0].selectionSet.selections.map(field => field.name.value);
        return keys;
    }
}

更新:阅读GraphQL Server Basics: Demystifying the info Argument in GraphQL Resolvers上的这篇文章后,我了解到fieldNodes是抽象语法树(AST)的摘录,而操作是的AST整个查询。

关于为什么安全地选择fieldNodes(fieldNodes[0])数组中的第一个对象的原因,是因为摘录从当前字段开始,而不是查询的根。

因此,@ pooya-haratian的方法是正确的。我只是添加了详细说明,并使用了NestJS的装饰器(@Info)。