Apollo Kotlin 中声明式缓存 ID
当使用
在指定缓存 ID 时,建议您使用本文中描述的方法声明式地进行。
extend type Book @typePolicy(keyFields: "id")
对于高级用例,您也可以编程式地定义缓存 ID。
它们是如何工作的
使用声明式缓存ID,代码生成过程会自动添加字段并生成可以返回任何有效缓存ID的类型安全代码。
为此,Apollo Kotlin 扩展了您的后端模式。GraphQL 规范支持对象扩展,使用extend type
关键字。我们可以结合使用@typePolicy
和@fieldPolicy
指令,以及一个命名为extra.graphqls
的额外.graphqls
文件。
请注意extra.graphqls
文件需要包含在你的模式配置<风格=“css assets-earthmark atom<<( https://apollo.graphql.net.cn/docs/kotlin/advanced/plugin-configuration#combining-multiple-schema-files?referrer=docs-content_START )中。
从以下两个来源之一,您可以获取给定对象类型的缓存ID:
来源 | 指令 | 描述 |
---|---|---|
从响应对象的字段中(例如,Book.id ) | @typePolicy | 这发生在网络请求之后,对于将查询结果与现有缓存数据合并至关重要。这最常见。 |
从字段的参数中(例如,author(id: "au456") ) | @fieldPolicy | 这发生在网络请求之前,可以在已缓存所有请求数据的情况下避免网络往返。这是一种可选的优化,可以避免一些缓存不命中。 |
@typePolicy
@typePolicy
指令允许您从一个对象的返回结果中指定的 key fields 来指定对象的缓存ID,这是您的 GraphQL 服务器所返回的。最常见的做法是使用对象的 id
域作为它的 key field。
例如,假设我们的schema.graphqls
文件包括以下定义:
type Book {id: String!author: Author!title: String!}
我们可以在与我们的模式相同的目录中的 extra.graphqls 文件中添加以下定义:
extend type Book @typePolicy(keyFields: "id")
Apollo Kotlin现在知道如何使用Book类型的id
字段来生成其缓存的ID。一个缓存记录现在可能看起来像这样:
"Book:bk123": {"id": "bk123", "title": "Les guerriers du silence", "author": "ApolloCacheReference{favoriteBook.author}"}
如果您需要通过多个键字段来唯一识别特定的缓存条目,则可以为对象指定多个键字段:
extend type Author @typePolicy(keyFields: "firstName lastName")
在这种情况下,Author
对象的缓存ID包含了其firstName
和lastName
字段的值:
"Author:PierreBordage": {"id": "au456", "firstName": "Pierre", "lastName": "Bordage"}
一个对象类型的所有键字段必须返回标量类型。
请注意,以这种方式指定的键字段将在代码生成期间自动添加到对象类型的选取中,因为它们总是需要用来在缓存中识别对象。这意味着您不需要在查询中包含它们。
将__typename
添加到您的操作中
除了键字段外,声明性缓存默认情况下还要求每个对象具有其__typename
。这些类型名称默认情况下不包括在内,因为它们会使非缓存用户查询更大。为了避免缓存未命中,请将__typename
添加到每个使用addTypename的选取中:
apollo {service("service") {addTypename.set("always")}}
@fieldPolicy
通过@fieldPolicy
指令,您可以根据您为特定字段提供的键参数值来指定对象的缓存ID。这使得您在发送网络请求之前就可以在缓存中识别一个对象,有可能完全跳过请求。
例如,假设我们的schema.graphqls
文件包括以下定义:
type Query {book(id: String!): Book}
我们碰巧知道这个 查询 找回任何一个 Book
对象,它有一个与所需 参数 匹配的 id
字段。因此,我们可以将该 id
参数作为此 字段 的一个关键字段。
我们可以在与我们的模式相同的目录中的 extra.graphqls 文件中添加以下定义:
extend type Query @fieldPolicy(forField: "book", keyArgs: "id")
Apollo Kotlin 现在知道在向 Query.book
发送网络请求之前,先要检查缓存以获取具有所提供 id
的 Book 对象。
.
请注意,尽管 @fieldPolicy
指令对应单个 字段,但是您将指令应用到 类型 定义(在这个例子中是 Query
)。这是因为 GraphQL 不允许扩展单个 字段。您使用 forField
参数来指定指令对应的 字段。
如果您想要指定多个关键字段参数以唯一标识某个缓存条目,您可以为字段指定 多个 关键 参数:
extend type Query @fieldPolicy(forField: "author", keyArgs: "firstName lastName")
在这种情况下,Author
对象的缓存 ID 包含其 firstName
和 lastName
字段值的组合,这两个字段都作为 Query.author
字段的 参数 提供。
如果一个对象类型有多个字段具有关键字段参数,您可以为该类型应用多个 @fieldPolicy
指令。