Apollo Federation中的实体
了解如何在多个子图中定义联邦类型
实体是Apollo Federation的基本构建块。在一个supergraph中,一个实体是一个可以在多个子图中解析其字段的对象类型。每个子图可以贡献不同的字段到实体,并只负责解析它所贡献的字段。这使子图能够遵循关注点分离原则。
例如,这个Product
实体的字段在两个子图中定义和解析:
type Product @key(fields: "id") {id: ID!name: String!price: Int}
type Product @key(fields: "id") {id: ID!inStock: Boolean!}
✅ 注意
只有 对象类型 可以是实体。
本指南介绍了如何在您的 子图模式 和代码中定义实体。
定义实体
要定义特定 子图 内的实体,请执行以下步骤:
- 将
@key
指令 应用到对象类型。 - 定义对象类型 参考解析器。
1. 定义 @key
在 子图模式 中,您可以通过向定义中添加 @key
指令来指派任何 对象类型 作为实体,如下所示:
type Product @key(fields: "id") {id: ID!name: String!price: Int}
在 @key
指令定义了实体的 唯一键,它由一个或多个类型的 字段
组成。在前面的示例中,Product
实体的唯一键是其 id
字段。实体的每个实例都必须通过其 @key
字段(s)唯一标识。键字段唯一性允许您的 路由器 将来自不同 子图 的字段与同一实体的实例相关联。
在大多数情况下,同一实体的 @key
字段(s)将在子图中相同。例如,如果一个子图使用 id
作为 @key
字段为 Product
实体,其他子图可能也会这样做。然而,这 并不强制要求。
若从数据库环境中来,将@key
视为一个实体的'主键并不完全准确,因为单个实体可以具有多个多个@key
。然而,您为实体的'@key
type Product @key(fields: "id") {id: ID!name: String!price: Int}
type Product @key(fields: "id") {id: ID!inStock: Boolean!}
有关定义高级键选项(如定义多个键或复合键)的更多信息,请参阅定义键指南。
键字段限制
实体的@key
不能包含:
- 字段返回联合类型或接口的字段
- 接受参数的字段
尽管不是严格要求,但最好为键使用不可为空的字段。如果您使用返回null
值的字段,GraphOS可能会遇到解析实体时的问题。
2. 定义引用解析器
在@key
指令中,实际上是在告知路由器,“如果您提供这个实体的唯一键,我可以解析这个实体的实例。”为此,个子图必须为该实体定义一个引用解析器。
✅ 注意
本节将描述如何在Apollo Server中创建引用解析器。如果您使用的是其他子图兼容的库,请参阅其文档以了解创建引用解析器或等效功能的方法。
对于上面定义的产品
实体,其引用解析器可能如下所示:
// Products subgraphconst resolvers = {Product: {__resolveReference(productRepresentation) {return fetchProductByID(productRepresentation.id);}},// ...other resolvers...}
让我们来分析这个示例
- 您可以在解析器映射中声明实体引用解析器,作为实体相应对象的一个成员。
- 引用解析器的名字总是
__resolveReference
- 引用解析器第一个参数是正在解析的实体的表示。
- 实体表示是一个对象,包含实体的
@key
字段,加上其__typename
字段。这些值由您的路由器自动提供给您子图。
- 实体表示是一个对象,包含实体的
- 引用解析器负责返回子图定义的所有实体字段。
- 在这个示例中,假设的
fetchProductByID
函数根据其id
获取某个产品
的属性数据。
- 在这个示例中,假设的
每个为实体贡献至少一个唯一字段的子图必须定义实时体的引用解析器。
要了解更多关于Apollo Server中的__resolveReference
的信息,请参阅API文档
下一步
一旦您 发布您的更新后的子图模式, GraphOS 将其组合成一个 超级图模式。 查询您的超级图的客户端可以与 实体 字段交互,而无需知道哪些子图贡献了哪些字段的具体细节。
了解关于更高级使用实体的方式,请查看以下指南