于10月8日至10日在纽约市加入我们,学习关于GraphQL联盟和API平台工程的最新技巧、趋势和新闻。加入2024年纽约市GraphQL峰会
文档
免费开始

Apollo Federation指令

Apollo Federation特定GraphQL指令的参考


定义了一组,您可以在您的中使用这些指令以启用某些功能。

导入指令

要在Federation 2子图模式中使用联邦指令,将以下格式的指令应用于schema类型:@link 的以下格式应用于schema类型:

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key", "@shareable"])

如果您有一个现有的schema声明,则可以应用此指令,或者应用新的extend schema声明(如上图所示)。

修改import数组以包含你的子图模式所需的任何联盟指令。上面的例子中导入的是@key@shareable指令(这些是最常用的)。

💡 提示

确保在指令名称中包含@符号。

重命名指令

如果导入的指令的默认名称与你的自定义指令之一相匹配,你可以使用以下语法重命名导入的指令:

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: [{ name: "@key", as: "@uniqueKey"}, "@shareable"])

此例子图模式使用@uniqueKey用于联盟指令(通常名为@key)。

命名空间指令

如果你没有从链接的规范中导入特定的指令,你仍然可以在你的子图模式中使用该指令。然而,该指令具有前缀:

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key"])
type Book @federation__shareable {
title: String!
}

在上面的例子中,@shareable没有从联盟规范中导入。因此,它以@federation__shareable的形式可用。

导入的@link指令的默认命名空间前缀是其关联规范(通过url的倒数第二个组件指示)的名称,加两个下划线(__)。对于 Apollo Federation 指令,此前缀是federation__

你可以通过为@link提供来自定义特定规范的命名空间前缀:

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
as: "fed")
type Book @fed__shareable {
title: String!
}

如图所示,自定义命名空间前缀以两个下划线结束。

directive @link(
url: String!,
as: String,
for: link__Purpose,
import: [link__Import]
) repeatable on SCHEMA

指令将外部规范的定义链接到此模式。每个 Federation 2 都使用@link指令来导入本文中描述的其它联盟特定指令(参见导入指令中的语法)。

有关更多关于@link的信息,请参阅官方规范

管理类型

@key
因为1.0

directive @key(fields: FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE

指定一个为一个并指定其键。键字段是一组子图可以使用以唯一标识实体的任何实例的字段。

type Product @key(fields: "id") {
id: ID!
name: String!
price: Int
}

💡 提示

要了解关于 @key 的最佳实践和高级用法,请参阅以下指南:

如果您使用的子图库支持可重复指令,则可以为单个实体应用多个 @key 指令以指定多个有效的键字段集:

type Product @key(fields: "upc") @key(fields: "sku") {
upc: ID!
sku: ID!
name: String
}

注意

要检查您的子图库是否支持可重复指令,请参阅 repeatable @key 项,位置在 Federation 兼容子图实现

在 Apollo Federation 2.3 及更高版本中,您还可以将 @key 应用到 interface 定义中来创建 实体接口。如果在 Federation 2 的早期版本中将 @key 应用到 interface 上,会发生 错误。

参数

名称
类型
描述
字段

FieldSet!

必填。GPU 作为字符串提供的 的唯一键贡献的

示例

  • "id"
  • "username region"
  • "name organization { id }"

另请参阅 高级代码 class="css-1lvdtfu">@key

可解析的

布尔值

如果f a l s e,则向指示此子图没有为该实体定义一个引用解析器。这意味着路由器无法 "跳转" 到此子图以解析不在其他子图中定义的字段。

通常,在 引用实体而不贡献字段时,将此参数设置为 false

默认值是 true

接口对象
因为2.3

directive @interfaceObject on OBJECT

表示一个对象定义是一个子图实体的接口抽象。这种抽象使子图能够自动向实现特定实体接口的所有实体贡献字段。

在构成过程中,每个@interfaceObject的字段既被添加到其相应的接口定义中,也被添加到实现该接口的所有实体类型中。

了解有关实体接口的更多信息。

@extends
因为1.0

directive @extends on OBJECT | INTERFACE

表示一个对象或接口定义是该类型另一个定义的扩展。

⚠️ 注意

如果你的子图库支持GraphQL内置的extend关键字,请不要使用此指令。相反,使用extend

此指令用于与不支持extend关键字,且通常通过程序生成其模式而不是使用静态.graphql文件的GraphQL子图库一起使用。

注意

Federation 2不需要使用类型。

在Federation 1中,每个子图都必须扩展QueryMutation类型(如果它们定义了这些类型),并且实体在定义它们的每个子图中扩展,除了它们的原始子图。

管理共享字段

@shareable
因为2.0

directive @shareable repeatable on FIELD_DEFINITION | OBJECT

注意

@shareable仅在v2.2及以后版本中可重复。

表示允许多个子图解析对象类型的字段(默认情况下,Federation 2中,对象字段只能由一个子图解析)。

type Position {
x: Int! @shareable
y: Int! @shareable
}

如果应用于对象类型定义,则该类型的所有字段都视为@shareable

type Position @shareable {
x: Int!
y: Int!
}

如果一个字段在某个子图中标记了@shareable,则必须在每个定义该字段的Federation 2子图中将其标记为@shareable@external

注意

如果一个Federation 2包含一个Federation 1子图,则Federation 1子图中的所有值类型都会被Federation 2组合算法自动视为@shareable

如果一个 字段 包含在实体的 @key 指令 中,那么该字段自动被认为是 @shareable 并且相应的子图(s)中不需要该指令。

另请参阅 Apollo Federation 中的值类型 以及 解析另一个子图的字段

关于 @shareable 指令,它用于指示一个对象 字段 可以被多个 子图 解析。由于接口字段不是直接解析的(它们的实现是), @shareable 在接口字段上没有意义,并且不允许(至少从联盟 2.2 版起;早期联盟版本错误地在接口字段上忽略了 @shareable)。

@inaccessible
因为2.0

directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

指示子图模式中的定义应从路由器的 API 模式 中省略,即使该定义也存在于其他子图。这意味着该字段根本不会暴露给客户端。

使用 @inaccessible 的常见用例包括:

  • 在更新跨越多个 子图 共享的定义(例如,值类型)时避免 组合错误
  • 在不将 字段 暴露给客户端的情况下,将字段作为实体 @key 的一部分使用

注意

与大多数指令不同, 保留了此指令的使用。有关保留其他指令的信息,请参阅 @composeDirective

因此,如果您 重命名此指令,则必须在每个子图中使用相同的名称。否则,由于名称不匹配,将发生组合错误。

子图 A
type Position @shareable {
x: Int!
y: Int!
z: Int! @inaccessible
}
子图 B
type Position @shareable {
x: Int!
y: Int!
# Subgraph is not yet updated
}

通常,当您在某个子图中添加一个附加值类型字段时,组合将失败,因为该字段在其他子图中不可解析。使用 @inaccessible,您可以在将字段添加到其他子图中时保留组合。当推广完成时,您可以删除指令并开始使用该字段。

一个不可访问的字段或类型未被省略在图模式中,因此路由器仍然知道它的存在(但客户端不能将其包括在 )。这使得路由器可以在组合来自多个子图的实体字段时,使用不可访问的字段作为实体 @key 的一部分。

如果一个类型被标记为 @inaccessible,则必须将该类型返回的所有字段也标记为 @inaccessible。否则,将发生组合错误。

有关更多信息,请参阅 使用 @inaccessible

@override
因为2.0

directive @override(from: String!) on FIELD_DEFINITION

表明一个对象字段现在由该子图而不是另一个已定义的子图解析。这使得您可以迁移一个字段从一个子图到另一个子图。

您可以将 @override 应用于 实体字段 以及根 类型(如 QueryMutation)的字段。

产品子图
type Product @key(fields: "id") {
id: ID!
inStock: Boolean!
}
库存子图
type Product @key(fields: "id") {
id: ID!
inStock: Boolean! @override(from: "Products")
}

在上面的例子中,我们将 Product.inStock 字段从产品 子图迁移到库存子图。组合的图模式显示,即使在产品子图中也定义了该字段,但 Product.inStock 的解决是通过库存子图而非产品子图。

您可以将 @override 应用到 @shareable 字段。如果这样做,则只有一个提供的子图的 from 参数不再解析该字段。其他子图仍然可以解析该字段。

只能有一个子图可以 @override 某个给定的字段。如果多个子图尝试 @override 相同字段,则发生组合错误。

有关更多信息,请参阅 迁移实体和根字段

渐进式 @override 是 GraphOS 路由器的一个 企业特性,需要组织订阅 才能使用。GraphOS 企业计划。如果您的组织没有企业计划,您可以免费试用企业版。

在生产 subgraph 上推出任何更改,包括字段迁移,可能会降低图的表现。一次性将所有流量从一个 subgraph 转到另一个 subgraph 可能会超载覆盖 subgraph。

渐进式 @override 特性允许以渐进式、逐步部署带有 @override 字段的 subgraph。作为 subgraph 开发者,您可以为覆盖和被覆盖 subgraph 对字段各自解决流量比例进行自定义。您可以为 @override 字段应用标签以设置应该由覆盖 subgraph 解决的流量百分比,其余部分由被覆盖的 subgraph 解决。然后您可以在 Studio 中监控 subgraph 的性能,解决问题,并迭代地逐步增加百分比,直到所有流量都被覆盖 subgraph 解决。

有关更多信息,请参阅 使用 @override 的增量迁移指南。

参数

名称
类型
描述
from

String!

必需。不再解决字段的另一个 subgraph 的名称。

  • 如果您正在使用 进行组合,则此名称必须与注册到 的 subgraph 相匹配。
  • 如果您使用 进行组合,则此名称必须与您提供给 rover supergraph compose 的 YAML 配置文件中的 subgraph 名称匹配。
label

String

此参数在 Apollo Federation 2.7 及以后版本中可用。它是 GraphOS 路由器的一个 企业特性,需要组织订阅 GraphOS 企业计划。您可以通过注册免费的企业版进行测试。

可选。任意。本版本中支持:

  • percent(<percent-value>) - 该子图解析的字段流量百分比。剩余百分比由其他(子图解析。了解更多,请参阅@override

控制访问

指令是GraphOS Router的企业功能,需要具有GraphOS企业计划的组织。如果您的组织没有企业计划,可以通过注册企业试用进行测试。

directive @authenticated on
FIELD_DEFINITION
| OBJECT
| INTERFACE
| SCALAR
| ENUM

表示目标元素仅供身份验证的超级图用户访问。欲了解更多精确访问控制,请参阅下面的@requiresScopes指令。有关更多详细信息,请参阅路由器文章

指令是GraphOS Router的企业功能,需要具有GraphOS企业计划的组织。如果您的组织没有企业计划,可以通过注册企业试用进行测试。

directive @requiresScopes(scopes: [[federation__Scope!]!]!) on
FIELD_DEFINITION
| OBJECT
| INTERFACE
| SCALAR
| ENUM

表示目标元素仅供拥有适当JWT权限范围的已验证超级图用户访问。有关更多细节,请参阅路由器文章

参数

名称
类型
描述
权限范围

[federation__Scope!]!

必需。列出需要授予用户以访问相关元素数据的JWT权限范围。

@policy
因为2.6

指令是GraphOS Router的企业功能,需要具有GraphOS企业计划的组织。如果您的组织没有企业计划,可以通过注册企业试用进行测试。

directive @policy(policies: [[federation__Policy!]!]!) on
| FIELD_DEFINITION
| OBJECT
| INTERFACE
| SCALAR
| ENUM

表示目标元素基于在Rahi脚本或协处理器中评估的授权策略进行限制。有关更多详细说明,请参阅路由器文章

参数

名称
类型
描述
策略

[federation__Policy!]!

必需。列出要评估的授权策略。

引用外部字段

@external
因为1.0

directive @external on FIELD_DEFINITION | OBJECT

表示该子图通常无法解析特定对象的字段,但仍然需要为了其他目的定义该字段。

该指令总是与引用对象字段的另一个指令结合使用,例如@provides@requires

库存子图
type Product @key(fields: "id") {
id: ID!
name: String! @external
inStock: Boolean!
}
type Query {
outOfStockProducts: [Product!]! @provides(fields: "name")
discontinuedProducts: [Product!]!
}

本示例 子图 通常无法解析 Product.name 字段,但它可以在 Query.outOfStockProducts 路径(由 @provides 指令 指示)解析这些字段。

如果应用于一个 对象类型 定义,该类型的所有 字段 都被视为 @external:

type Position @external {
x: Int!
y: Int!
}

@provides
因为1.0

directive @provides(fields: FieldSet!) on FIELD_DEFINITION

指定一组 实体字段,子图可以解析,但仅限于特定的模式路径(在其他路径上,子图无法解析这些字段)。

如果一个 子图始终可以解析特定的实体字段,请不要使用此指令。

使用此 指令始终是一个可选项优化。它可以减少路由器需要与之通信以解决某些操作的总子图数,从而提高性能。

库存子图
type Product @key(fields: "id") {
id: ID!
name: String! @external
inStock: Boolean!
}
type Query {
outOfStockProducts: [Product!]! @provides(fields: "name")
discontinuedProducts: [Product!]!
}

此示例子图可以解析 Query.outOfStockProducts 返回的产品的 Product.name,但不能解析 Query.discontinuedProducts

注意

如果一个 子图 @provides 一个实体字段:

  • 该子图必须定义该字段并标记为 @external,如上所示使用 Product.name
  • 实体字段必须在每个定义它的子图中被标记为 @shareable@external
  • 实体字段必须在至少另一个子图中标记为 @shareable(即至少有一个子图始终可以解析该字段)。

否则,会发生 组成错误。

有关更多信息,请参阅 使用 @provides

参数

名称
类型
描述
字段

FieldSet!

必需的。 一个 GraphQL 选择集(以字符串形式提供)的对象字段和子字段,子图只能在此查询路径上解决。

示例

  • "name"
  • "name address"
  • "... on Person { name address }"(适用于返回联合或接口的字段)

@requires
因为1.0

directive @requires(fields: FieldSet!) on FIELD_DEFINITION

表示特定实体字段的解析器依赖于由其他子图解析的其他实体字段的值。这告知路由器需要首先获取那些外部定义字段的值,即使原始客户端查询没有请求它们。

运输子图
type Product @key(fields: "id") {
id: ID!
size: Int @external
weight: Int @external
shippingEstimate: String @requires(fields: "size weight")
}

上面示例子图解析了Product对象的shippingEstimate字段,但它需要产品的sizeweight来执行此操作。由于这两个字段由不同的子图解析,它们被标记为@external

注意

如果一个子图使用@requires实体字段,该子图必须定义该字段并将其标记为@external,如上例中的Product.sizeProduct.weight所示。否则,将发生组合错误。

另请参阅贡献计算实体字段

参数

名称
类型
描述
字段

FieldSet!

必需。一个GraphQL选择集(以字符串形式提供)包含此字段所需的@external对象字段和子字段。

示例

  • "name"
  • "name address"
  • "name organization { id }"

应用元数据

@tag
因为1.1

directive @tag(name: String!) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA

将任意字符串元数据应用到模式位置。自定义工具可以在流程的任何步骤中使用此元数据,包括组合、静态分析和文档。GraphOS Enterprise的合约功能使用@tag及其包括和排除过滤器。

注意

与其他指令不同,组合会保留在生成的超级图模式中对此指令的使用。要保留其他指令的使用,请参阅@composeDirective

因此,如果您重命名此指令,您必须在每个使用它的子图中使用相同的名称。否则,由于命名不匹配,将发生组合错误。

extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@tag"])
type Query {
customer(id: String!): Customer @tag(name: "team-customers")
employee(id: String!): Employee @tag(name: "team-admin")
}
interface User @tag(name: "team-accounts") {
id: String!
name: String!
}
type Customer implements User @tag(name: "team-customers") {
id: String!
name: String!
}
type Employee implements User @tag(name: "team-admin") {
id: String!
name: String!
ssn: String!
}

参数

名称
类型
描述
name

String!

必需。要应用的模式名称。

管理自定义指令

directive @composeDirective(name: String!) repeatable on SCHEMA

指示组合将子图模式中特定自定义类型系统指令的所有使用情况都保留在超级图模式中(默认情况下,组合从超级图模式中省略大多数指令)。

⚠️ 注意

不要与 可执行指令 一起使用。可执行指令在组合上有不同的规则。

extend schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@composeDirective"])
@link(url: "https://myspecs.dev/myDirective/v1.0", import: ["@myDirective", { name: "@anotherDirective", as: "@hello" }])
@composeDirective(name: "@myDirective")
@composeDirective(name: "@hello")
directive @myDirective(a: String!) on FIELD_DEFINITION
directive @hello on FIELD_DEFINITION

此指令有以下要求:

  • 确保您的 子图库 支持 @composeDirective 或尝试手动将 @composeDirective 定义添加到您的子图模式中。
  • 必须通过 @link 指令从核心规范导入,并定义和导入必须保留的指令。
  • 指定的 name 必须与在此子图中用于指令的名称匹配。
    • 如果您在 @link 定义中使用了 as 参数以修改指令的名称,从规范默认名称变为修改后的名称,提供修改后的名称,而不是默认名称。
  • 如果多个子图导入和使用该指令:
    • 所有这些子图使用的指令名称必须相同。
    • 所有这些子图应使用由指令定义的同一主要版本的规范。

如果上述要求有任何一项未满足,组合 将失败。

如果不同的子图使用了指令对应规范的不同的版本,则超图模式使用所有子图中版本号码最高的版本。 将不会验证此版本的指令是否与使用较早版本的子图兼容。

参数

名称
类型
描述
name

String!

必需。 保留的组合中指令的名称(包括前缀 @)。

使用上下文保存和引用数据

@context
因为2.8

企业试用版

directive @context(name: String!) on OBJECT | INTERFACE | UNION;

@context 指令定义了一个命名上下文,从该上下文中可以传递到一个带有 @fromContext 指令的字段接收器注解的字段。接收器必须是一个带有注解的字段 @fromContext

每个 @context 都必须用名称进行定义,并且每个 @context 名称可以应用于子图内部的多个位置。例如:

type A @key(fields: "id") @context(name: "userContext") {
id: ID!
prop: String!
}
type B @key(fields: "id") @context(name: "userContext") {
id: ID!
prop: String!
}
type U @key(fields: "id") {
id: ID!
field (arg: String @fromContext(field: "$userContext { prop }")): String!
}

@fromContext
因为2.8

The @fromContext 指令用于设置从哪获取注解字段的值。该上下文必须已经使用 @context 指令进行了定义。

scalar ContextFieldValue;
directive @fromContext(field: ContextFieldValue) on ARGUMENT_DEFINITION;

在字段上必须使用 @fromContext 指令作为参数。其字段值——ContextFieldValue (标量)——必须包含定义的上下文名称和从上下文类型中选择字段的选项。

@fromContextContextFieldValue 中使用的选择语法类似于 GraphQL 字段选择语法,但有一些附加规则:

  • 第一个元素必须是使用 @context 定义的一个上下文名称,前面加上 $ (例如,$myContext)。这是唯一可以被注解字段引用的上下文。
  • 不能使用 @skip@include 指令。
  • 第二个元素必须是一个选择集,它可以解析为单个字段。
  • 顶层数据类型条件不得相互重叠,以便字段可以解析为单个值。
  • ContextFieldValue 中引用的所有字段必须都在当前子图中表达。如果字段跨越多个子图引用,它们必须带有 @external 注释。
  • 参数必须为可空。因为是按子图级进行验证,所以当合并子图时(比如当一个字段在一个子图中为可空,而在另一个子图中不可空时),所引用的字段可能会变成可空的。

当在多个地方设置相同的上下文值时,ContextFieldValue 必须将每个位置的每个类型解析为一个单一值,该值与参数类型相匹配。

有关使用 @context@fromContext 的示例,请参阅 使用上下文在类型层级共享数据

上页
共享类型(值类型)
下页
从 Schema Stitching 迁移
评估文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc., Transaction Apollo GraphQL。

隐私政策

公司