贡献和参考实体字段
跨子图贡献和参考实体字段
在联合架构中GraphQL架构中,单个子图可以向共享实体贡献并引用字段。本指南解释了子图如何协同工作以构建统一的模式,并通过添加和计算实体字段以及不添加字段而仅引用实体的示例。
贡献实体字段
任何数量的不同子图可以向实体定义添加字段。以下示例中,Product
实体:
type Product @key(fields: "id") {id: ID!name: String!price: Int}
type Product @key(fields: "id") {id: ID!inStock: Boolean!}
默认情况下,每个子图都必须贡献不同的字段,但是有一个重要的例外,就是@key
字段。如果多个子图尝试贡献相同的字段,就会发生一个组合错误。
贡献字段的每个子图必须为该实体定义一个引用解析器。
贡献计算实体字段
您可以从其他实体字段计算字段定义实体字段,即使是不同的子图解析这些字段的情况。
例如,这个Shipping子图为Product实体添加了一个shippingEstimate
字段。此字段基于产品的大小和重量进行计算,而Product子图定义了这些属性:
type Product @key(fields: "id") {id: ID!size: Int @externalweight: Int @externalshippingEstimate: String @requires(fields: "size weight")}
type Product @key(fields: "id") {id: ID!name: String!price: Intsize: Intweight: Int}
注意Shipping子图使用了两个指令:
- @requires 指令指示需要从其他子图获取哪些字段。
- @external 指令应用于类型定义中的所需字段。
- 此指令告诉 路由器,“这个子图知道这些字段存在,但它无法自行解析它们。”
路由器如何处理计算实体字段
在前面的例子中,如果查询请求产品的shippingEstimate
,路由器会做以下操作:
- 它会查询Product子图以获得产品的大小和重量。
- 它会查询Shipping子图以获得产品的
shippingEstimate
。
它会包含传递给
shippingEstimate
解析器的Product对象的大小和重量:resolvers.js{Product: {shippingEstimate(product) {return computeShippingEstimate(product.id, product.size, product.weight);}}}
使用@requires
与包含子字段的对象
如果一个计算字段 @requires
需要一个返回对象类型的字段,你还需要指定该对象哪些子字段是必需的。你可以使用以下语法列出这些子字段:
type Product @key(fields: "id") {id: ID!dimensions: ProductDimensions @externalshippingEstimate: String @requires(fields: "dimensions { size weight }")}
在此前的示例修改中,size
和 weight
现在是ProductDimensions
对象中的子字段。产品和运输子图必须都定义ProductDimensions
类型,这才能有效。
使用@requires
处理带参数的字段自2.1.2
从Federation v2.1.2版本开始,@requires
指令可以包含带参数的字段:
type Product @key(fields: "id") {id: ID!weight(units: String): Int @externalshippingEstimate: String @requires(fields: "weight(units:\"KILOGRAMS\")")}
以下规则适用
- 路由器在其查询中为定义所需字段的子图提供指定的值。
- 每个指定的参数值是静态的;路由器始终提供相同的值。
- 您可以省略可空参数的值。对于非可空参数,您必须提供值。
- 如果您在自己的子图模式中定义了SDL文件而不是按程序方式定义,您必须使用反斜杠转义字符串和枚举值的引号(如上所示)。
引用实体而不提供字段
您的子图可以使用一个实体作为字段的返回类型,而不向该实体提供任何字段。
例如,看看产品子图中的这个Product
实体:
type Product @key(fields: "id") {id: ID!name: String!price: Int}
假设您想创建一个包含以下Review
类型的Reviews
子图:
type Review {product: Product!score: Int!}
虽然这是可能的,但当前的Reviews
子图模式无效,因为它没有定义Product
实体。
要修复此问题,请将实体原型添加到Product
子图,如下所示:
type Review {product: Product!score: Int!}type Product @key(fields: "id", resolvable: false) {id: ID!}
占位符定义仅包括@key
实体的字段。在这种情况下,Product
类型定义仅包括id
字段。它还在@key
指令中包含resolvable: false
,以表示此子图没有为Product
实体定义引用解析器。