如何将“typeorm”模型转换为 graphql 有效负载?

Posted

技术标签:

【中文标题】如何将“typeorm”模型转换为 graphql 有效负载?【英文标题】:How to transform a `typeorm` model into graphql payload? 【发布时间】:2020-05-06 01:33:53 【问题描述】:

我正在开发一个微服务应用程序。我有一个 Node.js 服务充当“数据服务”并运行 nestjstypeormtype-graphql 模型。数据服务使用 https://github.com/nestjs/graphql 模块来启用 graphql 界面和 Playground。

我还有第二项服务,即客户端也订阅的“websocket 服务”。

“数据服务”使用 axios 库将 HTTP 请求发送到“websocket 服务”,然后这些请求通过 websocket 发送到客户端。从“数据服务”发送到“套接字服务”的消息包括typeorm 模型。当通过 axios typeorm 发送时,模型会通过 JSON.stringify。这就是问题所在。此stringify 转换包含不应出现在最终输出中的字段,并且还缺少 graphql 架构元数据。

我不想将模型字符串化,而是将它们转换为类似于 graphql 游乐场返回的 graphql 有效负载。据我所知,这个 graphql 转换被深度抽象掉了,并且发生在 nest/graphql 模块中的某个地方,该模块抽象了 apollo/server 模块。

这是一个复杂的系统,很难从中提取孤立的代码示例。如果有什么需要澄清的,请发表评论。以下是“数据服务”中的一些示例,我们有一个 Profile 实体,它具有 profile.entity.ts profile.service.tsprofile.resolver.ts

Profile 实体看起来像

import  Field, Int, ObjectType  from 'type-graphql'
import  Column, Entity, ManyToOne, OneToMany  from 'typeorm'
import  BaseEntity  from '../common/base/base.entity'


@ObjectType()
@Entity()
export class Profile extends BaseEntity 
  @Field()
  @Column( unique: true )
  public username: string

  @Field()
  @Column()
  public name: string

  @Field( nullable: true )
  @Column( nullable: true )
  public birthday?: Date

  // Relations

  @Column()
  public accountId: string

  @ManyToOne(type => Account, account => account.profiles,  eager: true )
  public account: Account

  

Profile 引用被检索并发送到套接字服务,如

    const profileReference = await this.profileService.fetchById(profileId)
    await this.socketService.sendHomeEvent(profileReference)

这里是我们想要获取 profileReference 并将其序列化为 graphql 响应负载的地方。 profileReference 上的 JSON.stringify 结果包括字段,特别是不应包括的 Account 字段。

【问题讨论】:

如果“数据服务”正在运行nest.js,这是否意味着除了“websocket服务”之外,您还通过它公开了一个面向客户端的API“websocket服务”是否也是一个GraphQL 服务(大概只是使用订阅)? @DanielRearden 是的,nestjs 的“数据服务”确实有一个面向客户端的 graphql API,也有一个 graphql apollo 游乐场。 “websocket 服务”没有任何 GraphQL 基础设施。 【参考方案1】:

给定一个 GraphQL 架构,您可以在服务器端执行任意查询。 type-graphql 公开了一个 buildSchema 用于从解析器类构建架构,如 here 所示。

import  buildSchema  from 'type-graphql'
import  graphql  from 'graphql'

const schema = await buildSchema(
  resolvers: [ProfileResolver],
)
const query = `
  # your query here
`
const root = 
const context = ...
const variables = ...
const  data, errors  = await graphql(schema, query, root, context, variables)

不幸的是,我不认为nest.js 暴露了它在后台构建的架构,所以你必须自己做。

【讨论】:

不幸的是,进一步看这并不能准确回答问题。此答案建议使用单独的 graphql 查询,而不是使用对已经可用的 typeorm 参考的引用。 您使用typeorm 的事实与您的架构无关。我不确定你在这里期待什么。您使用的装饰器仅告知type-graphql 如何从您提供的类生成模式。除了将实例作为查询的一部分实际返回之外,没有实用功能可以将模型实例转换为“GraphQL 有效负载”。 通过 GraphQL 执行将您的类实例强制转换为您看到的响应。 在我的示例中,我引用了 typeorm 对象; profileReference 从 Postgres 查询。此引用通过nestjs 中间件和apollo-server 传递并转换为graphql 响应。我想重新创建它。这个答案展示了一个完全独立且冗余的查询 冗余,是的,​​但不幸的是,鉴于您当前的架构,这是完成您所要求的事情的唯一方法。 “转换为 GraphQL 响应”部分仅在针对模式执行查询时发生。 如果您尝试获取 GraphQL 响应的唯一原因是因为序列化实例会公开您不想公开的实例上的属性,正如您在前面的问题中所指出的那样,那么你应该像我之前建议的那样使用自定义方法进行序列化。

以上是关于如何将“typeorm”模型转换为 graphql 有效负载?的主要内容,如果未能解决你的问题,请参考以下文章

使用 NestJS、TypeORM、GraphQL 更新具有实体之间关系的 PSQL 表

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

NestJS + Typeorm + Graphql:嵌套关系中 DTO 的正确设计模式

使用 TypeORM getManyWithCount 如何生成 PageInfo 进行分页

使用 typeorm 和 type-graphql 从 DB 检索数据时出错

如何将 AST 转换为 GraphQL