对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是不是正确?

Posted

技术标签:

【中文标题】对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是不是正确?【英文标题】:Is it semantically correct to use ID scalar type for a foreign key field in a Type-graphql and Typeorm entity?对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是否正确? 【发布时间】:2021-11-22 11:16:30 【问题描述】:

这是来自 GraphQL 的 documentation 的 StringID 的定义:

GraphQL comes with a set of default scalar types out of the box:

String: A UTF‐8 character sequence.

ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.

您会为Article 中的userId 字段使用ID 类型,它是User 实体的外键吗?还是您更喜欢 userIdString 类型,因为 id 字段是 Article 的唯一标识符,而不是 userId

@ObjectType()
@Entity()
export class Article 
  @Field((type) => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @Field()
  @Column( type: "text" )
  title: string;

  @Field(type => ID) // <<= ID or String?
  @Column(type: "uuid")
  userId: string

  @ManyToOne((type) => User, (user) => user.id)
  @JoinColumn( name: "userId" )
  user: User;

  @Field()
  @CreateDateColumn()
  created: Date;

  @Field()
  @UpdateDateColumn()
  updated: Date;



@ObjectType()
@Entity()
export class User 
  @Field((type) => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @Field()
  @Column( type: "text" )
  name: string;


【问题讨论】:

【参考方案1】:

在语义上,标量 ID 比标量 String 更有意义,因为根据定义它 represents a unique identifier, often used to refetch an object or as the key for a cache。它也不适合人类消费,是标量 ID 定义的另一部分。

从 GraphQL 的角度来看,它的唯一性并不重要,在同一类型中看到多个 IDs 是很常见的。使用它实际上是一种鼓励,它向您的消费者表明它可以(很可能)用于获取完整的对象。

现在您还必须完全挑战公开userId 的需求,因为这是一种非常“REST”的思维方式,并且它泄露了所使用的数据库关系模型,使得在不破坏的情况下发展您的数据模型变得更加困难更改架构。

通常您只会公开user: User 字段,因为它已经包含id 字段。有人可能会争辩说它会进行不必要的连接,但这可以通过前瞻轻松优化。如果消费者需要用户数据,他们可能需要的不仅仅是id,因此他们必须从数据库中获取整个对象。

【讨论】:

以上是关于对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章

使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法

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

type-graphql 找不到模块“类验证器”异常

如何在typeorm中查找id的数组属性包含某个id的实体

在 TypeORM 与 GraphQL 的多对多关系上使用数据加载器,查询多对多

不能对 Type-GraphQL 字段类型使用类型“对象”