以实体思考
使用实体设计模式的最佳实践
实体是联合图的核心构建模块,因此采用任何架构设计最佳实践时都必须考虑到实体的独特角色。尽管在子图中定义任何实体都没有要求,但联合图架构设计过程通常从考虑初始实体类型将如何以及如何在整个图中引用和扩展它们开始,以帮助在现在以及将来图中发展时保持子图之间的关注点分离。
根据需要定义、引用和扩展实体
Apollo Federation规范指出,可以通过向其子图架构中的定义添加@key
指令,将对象或接口类型转换为实体@key
指令定义了实体的唯一键及其fields
参数将包含类型的一个或多个字段。在以下示例中,Product
实体's primary key 是其upc
字段:
type Product @key(fields: "upc") {upc: String!name: String!description: String}
将 upc
字段设置为键意味着其他想要使用此实体 的子图将需要知道任何产品的至少这个值。我们定义的键应该是唯一标识资源 的值。这是因为我们希望避免他们在子图之间任意传递动态字段数据的场景查询 执行的情况。
在模式中定义一个 实体后,其他 子图可以在其模式中引用该实体。为了引用子图的模式有效,它必须在它的模式中定义实体的存根。例如,我们可以通过在 Product
子图中定义的 子图 中作为 product
字段返回类型对应的 Review
类型引用 Product
类型:
type Review {rating: Intproduct: Product}type Product @key(fields: "upc") {upc: String!}
@key
指令表明评论子图将能够通过其 UPC 值识别产品,因此可以根据 upc
主键字段连接到产品,但评论子图不需要了解有关给定产品的任何其他详细信息。
引用实体是联合体的关键特性,但只是故事的一半。虽然一个 实体将由单个 子图拥有,但其他子图可能希望向实体的类型添加更多 字段,以在图中提供更全面的实体表示。这样做和在源子图的非起源子图中添加额外字段一样简单。例如,评论子图的模式可能向在产品子图中最初定义的 Product
类中添加 reviews
字段:
type Review {rating: Intproduct: Product}type Product @key(fields: "upc") {upc: String!reviews: [Review]}
扩展实体时,重要的是要注意 实体的起源子图将不会意识到添加的字段。此外,实体中的每个 字段必须只定义一次,否则网关将遇到模式 组合 错误。
从实体开始工作
当从仅客户端或单体 GraphQL 模式迁移时,这项工作首先从较大模式中提取的第一个 子图中识别将要公开的实体。当从基于 BFF 的 GraphQL API 或任何包含多个重叠图的架构迁移时,识别实体(以及通常确定新的子图边界)的工作可能更复杂,需要一定程度的关于类型所有权以及可能对客户端造成中断性变化的迁移过程的协商。
无论您的架构起点是什么, Apollo Federation 都旨在允许以渐进的、非破坏性的方式完成识别实体和定义 子图边界的任务。开始识别这些实体也是采用以下其他模式设计最佳实践的基本先决条件。
关于实体使用和功能的更多信息,请参阅《实体文档页面实体。
@defer
和实体
实体不仅仅是用于在子图之间连接数据。您还可以使用实体来启用新的@defer
指令,用于客户端控制的响应数据优先级。GraphOS 路由器可以延迟处理实体字段(包括根字段)的解析,并按优先级将数据块发送回客户端。通过在图中对类型定义实体,客户端可以通过向其操作中添加指令来提高用户体验。