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

使用上下文来共享数据

在不过度加载@keys的情况下,沿着类型层次结构共享数据


@context@fromContext,属于Apollo企业功能的Apollo并且需要拥有一个

GraphOS Enterprise计划。如果你的组织没有企业计划,你可以通过注册一个免费的

为了让后代能访问祖先的 字段,你可以将其添加为 @key 字段到链中的每个 实体,但这可能会造成问题。deeply nested types 可能会改变许多实体的 @key 字段。添加的字段可能与其添加到的实体无关。最重要的是,过度使用 @key 字段经常打破不同 之间的关注点分离。

使用 @context@fromContext 指令,可以允许一个 在不加载 @key 字段的情况下共享 字段。您可以使用这些指令在一个 子图 中定义一个或多个 上下文。上下文提供了子图在嵌套类型层次结构中共享数据的方式,同时不会过度使用实体键中的无关字段。上下文还保持了不同子图之间的关注点分离。

使用一个上下文

以下是一个单一上下文的示例,下面的 子图 跟踪每个用户最后一次金融交易。 Transaction 类型是 User 类型的子类。每个交易都依赖于相关用户的货币来计算交易额。这种依赖性— currencyCode 参数—取决于用户的货币 的一User— 是通过上下文定义的。在 User 上的 @context 指令设置上下文,在 currencyCode 上的 @fromContext 获取上下文数据。

示例:使用 @context 和 @fromContext
scalar CurrencyCode;
type Currency {
id: ID!
isoCode: CurrencyCode!
}
type User @key(fields: "id") @context(name: "userContext") {
id: ID!
lastTransaction: Transaction!
userCurrency: Currency!
}
type Transaction @key(fields: "id") {
id: ID!
currency: Currency!
amount: Int!
amountInUserCurrency(
currencyCode: CurrencyCode
@fromContext(field: "$userContext { userCurrency { isoCode } }")
): Int!
}

注意

  • 上下文名称不能包含下划线。
    • 在上面的示例中,userContext 是一个有效的上下文名称,但 user_context 就不是。
  • @fromContext 的参数中不存在。相反,它由自动填充。
    • 在上面的示例中,参数 currencyCode: CurrencyCode! 不会出现在API架构中。

在 @fromContext 中使用类型条件

在这个示例中,注意@fromContext指令是如何使用一系列类型条件来选择访问Child.prop1时的所需字段。如果没有所有可能的上下文都有一个字段,那么就不需要类型条件,例如Child.prop2的情况。

示例:使用多个上下文
type Query {
a: A!
b: B!
c: C!
}
type A @key(fields: "id") @context(name: "context1"){
id: ID!
field: String!
someField: String!
child: Child!
}
type B @key(fields: "id") @context(name: "context1"){
id: ID!
field: String!
someField: String!
child: Child!
}
type C @key(fields: "id") @context(name: "context1") {
id: ID!
field: String!
someOtherField: String!
child: Child!
}
type Child @key(fields: "id") {
id: ID!
prop1(
arg: String!
@fromContext(field: "$context1 ... on A { someField } ... on B { someField } ... on C { someOtherField }")
): Int!
prop2(
arg: String!
@fromContext(field: "$context1 { field }")
): Int!
}

如果相同上下文值设置在多个位置——就像示例中的Child.prop1Child.prop2参数——那么FieldValue必须将每个位置的所有类型解析为单个与参数类型匹配的值。

注意

联接不保证如果字段可通过多个上下文访问,将使用哪个上下文。

区分上下文

当类型层次结构中的多个祖先实体可能满足一组上下文时,会选择最近的祖先。例如,如果类型的父亲和祖父母都能提供上下文的值,则选择父辈,因为它比父辈更接近。

在以下示例中,给定嵌套类型ABC,其中C引用的上下文可以是AB提供,C使用B的值,因为它是比A更近的祖先:

type Query {
a: A!
}
type A @key(fields: "id") @context(name: "context1") {
id: ID!
field: String!
b: B!
}
type B @key(fields: "id") @context(name: "context1") {
id: ID!
field: String!
c: C!
}
type C @key(fields: "id") {
id: ID!
prop(
arg: String! @fromContext(field: "$context1 { field }")
): Int!
}

在一个更复杂的中,一个字段可以通过多个路径访问,并且可以使用不同的字段根据使用的路径来解析prop

跨子图引用字段

上下文作用域的定义只能存在于一个 中。 @fromContext 指令不能引用其他 @context 子图中定义的上下文。然而,您可以使用上下文通过 @external 引用在不同子图间共享数据。

以重用 Transaction 示例 为例,想象一个用于处理 UserCurrency 类型子图

scalar CurrencyCode
type Currency @shareable {
id: ID!
isoCode: CurrencyCode!
}
type User @key(fields: "id") {
id: ID!
userCurrency: Currency!
}

如果您想从另一个子图中引用这些 字段,您可以使用 @external 指令在子图边界传递数据:

scalar CurrencyCode
type Currency @shareable {
id: ID!
isoCode: CurrencyCode!
}
type User @key(fields: "id") @context(name: "userContext") {
id: ID!
# This is a reference to the field resolved elsewhere
userCurrency: Currency! @external
# We add this field to our type here
lastTransaction: Transaction!
}
type Transaction @key(fields: "id") {
id: ID!
currency: Currency!
amount: Int!
amountInUserCurrency(
currencyCode: CurrencyCode
@fromContext(field: "$userContext { userCurrency { isoCode } }")
): Int!
}
上一页
解析另一个子图的字段
下一页
实体接口
评价文章评价Edit on GitHubEditForumsDiscord

©2024Apollo Graph Inc.(字号为 Apollo GraphQL)。

隐私政策

公司