类型 Graphql 自定义解析器

Posted

技术标签:

【中文标题】类型 Graphql 自定义解析器【英文标题】:Type Graphql custom Resolver 【发布时间】:2020-10-04 06:10:05 【问题描述】:

我有一个用户 ObjectType 并希望在我的 LoginResolver 中将用户和为该用户生成的令牌作为对象返回,如下所示:

user:User, token:string 目前我可以返回用户或字符串,具体取决于我在 @Mutation() 装饰器中给出的类型

@Mutation((returns) => User)
  async login(
    @Arg("email") email: string,
    @Arg("password") password: string,
    @Ctx("ctx") ctx: IContext
  ) 
    const user = await this.userRepo.findOneUser( where:  email  );
    const success = await compare(password, user.password);
    if (!success) ctx.throw(401);
    const token = await this.tokenRepo.createToken(user);

    return user;
  

当我尝试创建一个 UserWIthToken 对象类型时,用户实体上的每个字段都会出现以下错误:

app_1       |   error: [ValidationError: Cannot query field "id" on type "UserWithToken".] 
app_1       |     locations: [ [Object] ],
app_1       |     path: undefined,
app_1       |     extensions:  code: 'GRAPHQL_VALIDATION_FAILED', exception: [Object] 
app_1       |   
app_1       | ```
dont mind the app_1 here, Iam using docker

【问题讨论】:

【参考方案1】:

您需要为这种情况创建一个自定义的 ObjectType

@ObjectType()
class UserWithToken 
    @Field(() => User)
    user: User
      
    @Field()
    token: string

然后在查询中使用该对象而不是用户

@Query((returns) => UserWithToken)
async login(
    @Arg("email") email: string,
    @Arg("password") password: string,
    @Ctx("ctx") ctx: IContext
) : Promise<UserWithToken> 
    const user = await this.userRepo.findOneUser( where:  email  );
    const success = await compare(password, user.password);
    if (!success) ctx.throw(401);
    const token = await this.tokenRepo.createToken(user);

    return 
        user,
        token
    ;

请注意,我在这里使用了@Query 而不是@Mutation,因为它更适合这种情况,根据经验,如果您想在不修改数据的情况下读取数据,请使用查询,否则删除/添加/编辑数据使用突变。

然后你可以像这样运行登录查询

query 
  login(email: "xx@xx.com", password: "xxxxx") 
    token
    user 
      id
      name
      email
      ...
    
  

【讨论】:

谢谢你的回复,我更新了问题,还是有一些错误 您似乎是在尝试直接从UserWithToken 对象查询用户字段,我更新了有关如何正确查询用户数据的答案。 啊对,我没有相应地更新查询谢谢:) 有可能,例如tokenRepo.createToken 可以在 db 的列中写入时间戳来记录上次发布日期,所以在这种情况下最好使用突变。同样从客户端的角度来看,当我们通过查询发出令牌时,这意味着 apollo 可以使用缓存值,而对于突变,它将始终被执行。 谢谢@MichałLytek 我从来没有想过这种情况!

以上是关于类型 Graphql 自定义解析器的主要内容,如果未能解决你的问题,请参考以下文章

将自定义 GraphQL 解析器和类型添加到 Prisma/Nexus 架构中

ElasticSearch03_Mapping字段映射常用类型数据迁移ik分词器自定义分词器

ElasticSearch03_Mapping字段映射常用类型数据迁移ik分词器自定义分词器

商城项目18_esMapping字段映射常用类型数据迁移ik分词器自定义分词器

商城项目18_esMapping字段映射常用类型数据迁移ik分词器自定义分词器

ElasticSearch03_Mapping字段映射常用类型数据迁移ik分词器自定义分词器