跳到主要内容

Relay Node 接口

在本节中,我们将延续 GraphQL 示例,讲解如何实现 Relay Node 接口。如果您不熟悉 Node 接口,请阅读以下摘自 relay.dev 的说明:

为了给 GraphQL 客户端提供优雅处理缓存和数据重新获取的方案,GraphQL 服务端需要以标准化方式暴露对象标识符。在查询中,模式应提供通过 ID 请求对象的标准机制。在响应中,模式需提供这些 ID 的标准表示方式。

我们将带有标识符的对象称为“节点”。以下查询示例展示了这两种情况:

  {
node(id: "4") {
id
... on User {
name
}
}
}

克隆代码(可选)

本教程的代码可在 github.com/a8m/ent-graphql-example 获取,每个步骤都对应 Git 标签。如果您想跳过基础设置,直接从 GraphQL 服务器的初始版本开始,可以按以下方式克隆仓库:

git clone git@github.com:a8m/ent-graphql-example.git
cd ent-graphql-example
go run ./cmd/todo/

实现

Ent 通过其 GraphQL 集成支持 Node 接口。只需几个简单步骤即可在应用中添加支持。我们首先通过编辑 gqlgen.yaml 文件告知 gqlgen:Ent 提供了 Node 接口:

gqlgen.yml
# 此部分声明 GraphQL 与 Go 类型系统之间的映射关系
models:
# 将 ID 字段定义为 Go 的 'int' 类型
ID:
model:
- github.com/99designs/gqlgen/graphql.IntID
Node:
model:
- todo/ent.Noder

要应用这些更改,我们重新运行代码生成:

go generate .

与之前一样,我们需要在 ent.resolvers.go 中实现 GraphQL 解析器。只需一行代码更改,我们就可以通过以下方式替换生成的 gqlgen 代码:

ent.resolvers.go
func (r *queryResolver) Node(ctx context.Context, id int) (ent.Noder, error) {
- panic(fmt.Errorf("not implemented: Node - node"))
+ return r.client.Noder(ctx, id)
}

func (r *queryResolver) Nodes(ctx context.Context, ids []int) ([]ent.Noder, error) {
- panic(fmt.Errorf("not implemented: Nodes - nodes"))
+ return r.client.Noders(ctx, ids)
}

查询节点

现在我们已经准备好测试新的 GraphQL 解析器。首先通过多次运行以下查询创建几个待办事项(修改变量可选):

mutation CreateTodo($input: CreateTodoInput!) {
createTodo(input: $input) {
id
text
createdAt
priority
parent {
id
}
}
}

# 查询变量: { "input": { "text":"Create GraphQL Example", "status": "IN_PROGRESS", "priority": 1 } }
# 输出: { "data": { "createTodo": { "id": "2", "text": "Create GraphQL Example", "createdAt": "2021-03-10T15:02:18+02:00", "priority": 1, "parent": null } } }

对某个待办事项运行 Node API 将返回:

query {
node(id: 1) {
id
... on Todo {
text
}
}
}

# 输出: { "data": { "node": { "id": "1", "text": "Create GraphQL Example" } } }

对多个待办事项运行 Nodes API 将返回:

query {
nodes(ids: [1, 2]) {
id
... on Todo {
text
}
}
}

# 输出: { "data": { "nodes": [ { "id": "1", "text": "Create GraphQL Example" }, { "id": "2", "text": "Create Tracing Example" } ] } }

完成!如您所见,通过更改几行代码,我们的应用现已实现 Relay Node 接口。在下一节中,我们将展示如何使用 Ent 实现 Relay 游标连接规范,这对于支持查询结果的切片和分页非常有用。