Nestjs / GraphQL - Playground 为查询返回 Null 错误。我的解析器?

Posted

技术标签:

【中文标题】Nestjs / GraphQL - Playground 为查询返回 Null 错误。我的解析器?【英文标题】:Nestjs / GraphQL - Playground Returns Null Error For Query. My Resolvers? 【发布时间】:2019-07-30 19:47:12 【问题描述】:

我的浏览器中的 Playground 很好地显示了 Nestjs 创建的架构,但查询返回 null。我的代码有问题吗?

"errors": [
    
      "message": "Cannot return null for non-nullable field Query.getUsers.",
      "locations": [
        
          "line": 2,
          "column": 3
    

这意味着没有找到数据。

schema.graphql:

type UsersGQL 
    User_id: ID!
    first_name: String!
    last_name: String!
    main_skill_title: String!
    user_name: String!
    ....


type Query 
    getUser(user_id: ID!): UsersGQL!
    getUsers: [UsersGQL!]!

在 Nestjs 中使用 GraphQL 编译为 graphql.schema.ts

export class UsersGQL 
    user_id: string;
    first_name: string;
    last_name: string;
    main_skill_title: string;
    user_name: string;
    ...


export abstract class IQuery 
    abstract getUser(user_id: string): UsersGQL | Promise<UsersGQL>;

    abstract getUsers(): UsersGQL[] | Promise<UsersGQL[]>;

    abstract temp__(): boolean | Promise<boolean>;

users.resolvers.ts

import  Query, Resolver  from '@nestjs/graphql';
import  UsersService  from './users.service';

import  UsersGQL  from '../graphql.schema';
// import  UsersDTO  from './users.dto';


@Resolver('UsersGQL')
export class UsersResolvers 
  constructor(
    private readonly userService: UsersService
  ) 

  @Query()
  async getUsers() 
    return await this.userService.findAll();
  

该服务适用于我的 Nestjs REST API。数据库是 Postgres。

users.service.ts

import  Injectable  from '@nestjs/common';
import  InjectRepository  from '@nestjs/typeorm';
import  Repository, getManager, getRepository  from 'typeorm';
import  Members  from './members.entity';

@Injectable()
export class UsersService 

  private entityManager = getManager();

  constructor(
    @InjectRepository(Users)
    private readonly usersRepository: Repository<Users>
  ) 

  async findAll(): Promise<Users[]> 
    return await this.usersRepository.find();
  

游乐场查询:


  getUsers 
    first_name
    last_name
  

Playground 中返回的错误:


  "errors": [
    
      "message": "Cannot return null for non-nullable field Query.getUsers.",
      "locations": [
        
          "line": 2,
          "column": 3
        
      ],
      "path": [
        "getUsers"
      ],
      "extensions": 
        "code": "INTERNAL_SERVER_ERROR",
        "exception": 
          "stacktrace": [
             ...
  ],
  "data": null

编辑 - 添加了 users.module.ts、app.module.ts 和 ormconfig.json。这整个模块是延迟加载的。 REST 和 GraphQL 在模块中并列。我还分离了 REST 和 GQL 组件。

users.module.ts

import  Module  from '@nestjs/common';
import  TypeOrmModule  from '@nestjs/typeorm';

// REST
import  UsersService  from './users.service';
import  UsersController  from './users.controller';
import  Users  from './users.entity';

// GraphQL
import  UsersResolvers  from './users.resolvers';

@Module(
  imports: [
    TypeOrmModule.forFeature([
      Users
      ]),
  ],
  providers: [
    UsersService,
    UsersResolvers
  ],
  controllers: [UsersController],
)

export class UsersModule 

app.module.ts

import  Module, NestModule, MiddlewareConsumer  from '@nestjs/common';

import  TypeOrmModule  from '@nestjs/typeorm';
import  GraphQLModule  from '@nestjs/graphql';
import  join  from 'path';

import  LoggerMiddleware  from './logger.middleware';

import  UsersModule  from './users/users.module';

import  UsersController  from './users/users.controller';



@Module(
  imports: [
    TypeOrmModule.forRoot(),
    GraphQLModule.forRoot(
      typePaths: ['./**/*.graphql'],
      definitions: 
        path: join(process.cwd(), 'src/graphql.schema.ts'),
        outputAs: 'class',
      ,
      debug: true,
    ),
    UsersModule
  ],
  controllers: [
  ],
  exports: [
  ],
  providers: [
  ]
)

export class AppModule implements NestModule 
  configure(consumer: MiddlewareConsumer) 
    consumer
      .apply(LoggerMiddleware)
      .with('AppModule')
      .forRoutes(
        UsersController
    );

ormconfig.json

...
"entities": [
    "src/**/**.entity.ts,.js",
    // "src/graphql.schema.ts"  This doesn't work.  Must use REST entity.
  ],
...

【问题讨论】:

如果我使查询为空,删除“!”,那么查询结果是 "data": "getMembers": null 这似乎意味着没有返回数据通过目前对我的 REST api 运行良好的服务。 【参考方案1】:

您可能从'@nestjs/common' 导入@Query 而不是'@nestjs/graphql'

确保拥有:

import  Query  from '@nestjs/graphql';

【讨论】:

谢谢金,但我有这个权利。我之前发现了其他关于此的 SO 帖子并且很小心。此外,我刚刚为他的 Github 演示复制了 Kamil 的作品 :-) 好吧,可惜,这本来可以很容易解决的。 ;-) 您是否向您的服务添加了 console.log 并确保它被调用并且确实返回了一个非空数组? 您的服务中还有一个错字,但可能只是复制/粘贴:userssRepository 我确实将 console.log 放入了我的服务和解析器中,但 IDE 终端窗口中没有任何反应。 我会尝试,但我必须先了解代码沙箱。可能是明天,因为今天是妇女节,我的俄罗斯妻子想参加派对 :-) 我是美国人。所以如果你有一段时间没有收到我的消息,我还没有抛弃你。【参考方案2】:

TL;DR

您的架构已正确公开(并可通过 Playground 使用)这一事实并不一定意味着所有相应的模块和解析器都已集成到您正在运行的 Nest 应用程序中。


我最近遇到了同样的错误,原因很简单:我忘记将包含解析器的模块导入根模块——通常是AppModule

那么:您确定您已导入所有 UserModule 模块依赖项(尤其是 UserResolver)并将 UsersModule 本身导入到您的 AppModule 中吗?

这里的诀窍在于,您的服务器公开的 GraphQL 架构是直接从您的源文件生成的。根据您的 Nest GraphQL 配置,它会将所有.graphql.gql 文件一起编译(schema first approach);或 type-graphql 模块,使用 Nest v6,将读取所有源文件以查找其装饰器并生成 schema.gql (code first approach)。因此,即使没有实际模块解析您的请求,您也可以公开正确的模式。

IMO,这是框架的一个错误行为,因为它在不提供任何解释的情况下默默地无法解析您的架构。您收到的简单错误消息 (Cannot return null for non-nullable field Query.getUsers.) 非常具有误导性,因为它隐藏了真正的故障,即损坏的依赖关系

更多信息,这里是相关的 GitHub 问题:https://github.com/nestjs/graphql/issues/198

【讨论】:

谢谢@MarsLevin!是的,members.module 作为延迟加载被导入到 app.module 中。这就是我尝试设置 GraphQL 之前 REST 代码运行良好的原因。此后,我重构并分离了 GraphQL 组件,以便更轻松地进行故障排除。现在我可以让 Nestjs 编译。我收到错误No repository for "MembersGQL" was found. Looks like this entity is not registered in current "default" connection? 我已将重构的代码和模块以及 ormconfig.json 的一部分添加到我的原始帖子中。有什么想法吗? 我让它在 Playground 中向我的 Postgres DB 中的用户展示,但我不喜欢它必须使用 REST 实体。转换为 GraphQL 后,我想删除所有 REST。【参考方案3】:

这种 TypeORM 架构的“解决方案”是使用 TypeORM 实体。

users.resolvers.ts

import  Query, Resolver  from '@nestjs/graphql';
import  UsersService  from './users.service';
import  Users  from './users.entity';  // Here

@Resolver('Users')
export class UsersResolvers 
  constructor(
    private readonly userService: UsersService
  ) 

  @Query()
  async getUsers() 
    return await this.userService.findAll();
  

【讨论】:

以上是关于Nestjs / GraphQL - Playground 为查询返回 Null 错误。我的解析器?的主要内容,如果未能解决你的问题,请参考以下文章

NestJS 使用 GraphQL 上传 [关闭]

实现 GraphQLModule 时 GraphQL 的 NestJS 问题

错误:使用 Nestjs + Graphql + Typeorm 时无法确定 GraphQL 输入类型

更新nestjs/graphql后没有通过标头

NestJS:使用 graphql 的 Passport LinkedIn 策略

NestJS + Mongoose + GraphQL:“填充”不起作用