Ent项目:自动生成GraphQL过滤器指南
概述
Ent作为一个强大的Go语言实体框架,近期推出了自动生成GraphQL过滤器的功能。这项功能允许开发者直接从Ent的schema定义生成类型安全的GraphQL过滤器(即Where谓词),并能够无缝地将GraphQL查询映射到Ent查询。本文将详细介绍这一功能的背景、实现方式和使用方法。
背景与设计理念
Ent框架的核心设计原则之一是"通过代码生成提供静态类型和显式API"。这意味着对于开发者定义的每个实体,Ent都会生成明确、类型安全的代码,用于高效地与数据进行交互。
GraphQL作为一种API查询语言,同样强调类型安全。Ent与GraphQL的集成让开发者能够轻松创建与Ent映射的API服务器,进行数据库数据的增删改查操作。
自动生成GraphQL过滤器
生成过滤器输入类型
要为ent/schema
中的每种类型生成过滤器输入类型(如TodoWhereInput
),需要修改ent/entc.go
配置文件:
func main() {
ex, err := entgql.NewExtension(
entgql.WithWhereFilters(true),
entgql.WithConfigPath("../gqlgen.yml"),
entgql.WithSchemaPath("<PATH-TO-GRAPHQL-SCHEMA>"),
)
if err != nil {
log.Fatalf("creating entgql extension: %v", err)
}
err = entc.Generate("./schema", &gen.Config{}, entc.Extensions(ex))
if err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}
运行go generate ./ent/...
后,Ent会为schema中的每种类型生成对应的<T>WhereInput
类型,并自动更新GraphQL schema。
生成的过滤器类型示例
生成的过滤器类型包括:
// TodoWhereInput代表用于过滤Todo查询的where输入
type TodoWhereInput struct {
Not *TodoWhereInput `json:"not,omitempty"`
Or []*TodoWhereInput `json:"or,omitempty"`
And []*TodoWhereInput `json:"and,omitempty"`
// "created_at"字段谓词
CreatedAt *time.Time `json:"createdAt,omitempty"`
CreatedAtNEQ *time.Time `json:"createdAtNEQ,omitempty"`
CreatedAtIn []time.Time `json:"createdAtIn,omitempty"`
CreatedAtNotIn []time.Time `json:"createdAtNotIn,omitempty"`
CreatedAtGT *time.Time `json:"createdAtGT,omitempty"`
CreatedAtGTE *time.Time `json:"createdAtGTE,omitempty"`
CreatedAtLT *time.Time `json:"createdAtLT,omitempty"`
CreatedAtLTE *time.Time `json:"createdAtLTE,omitempty"`
// 其他字段谓词...
}
对应的GraphQL schema也会相应更新:
input TodoWhereInput {
not: TodoWhereInput
and: [TodoWhereInput!]
or: [TodoWhereInput!]
"""created_at字段谓词"""
createdAt: Time
createdAtNEQ: Time
createdAtIn: [Time!]
createdAtNotIn: [Time!]
createdAtGT: Time
createdAtGTE: Time
createdAtLT: Time
createdAtLTE: Time
# 其他字段谓词...
}
使用生成的过滤器
1. 修改GraphQL schema
在GraphQL schema中添加where参数:
type Query {
todos(
after: Cursor,
first: Int,
before: Cursor,
last: Int,
orderBy: TodoOrder,
where: TodoWhereInput,
): TodoConnection!
}
2. 在解析器中使用过滤器
在GraphQL解析器中使用生成的过滤器:
func (r *queryResolver) Todos(ctx context.Context, after *ent.Cursor, first *int, before *ent.Cursor, last *int, orderBy *ent.TodoOrder, where *ent.TodoWhereInput) (*ent.TodoConnection, error) {
return r.client.Todo.Query().
Paginate(ctx, after, first, before, last,
ent.WithTodoOrder(orderBy),
ent.WithTodoFilter(where.Filter),
)
}
过滤器规范
逻辑运算符
可以使用not
、and
和or
字段添加逻辑运算符:
{
or: [
{
status: COMPLETED,
},
{
not: {
hasParent: true,
status: IN_PROGRESS,
}
}
]
}
当提供多个过滤字段时,Ent会隐式添加And
运算符。
边/关系过滤器
边(关系)谓词可以使用与Ent相同的语法表达:
{
hasParent: true,
hasChildrenWith: {
status: IN_PROGRESS,
}
}
这将生成以下Ent查询:
client.Todo.
Query().
Where(
todo.HasParent(),
todo.HasChildrenWith(
todo.StatusEQ(todo.StatusInProgress),
),
).
All(ctx)
实际应用示例
假设我们需要查询所有状态为"COMPLETED"的待办事项,可以执行以下GraphQL查询:
query QueryAllCompletedTodos {
todos(
where: {
status: COMPLETED,
},
) {
edges {
node {
id
}
}
}
}
更复杂的查询示例如下:
query FilterTodos {
todos(
where: {
or: [
{
hasParent: false,
status: COMPLETED,
},
{
status: IN_PROGRESS,
hasParentWith: {
priorityLT: 1,
statusNEQ: COMPLETED,
},
}
]
},
) {
edges {
node {
id
}
}
}
}
总结
Ent的自动GraphQL过滤器生成功能将Ent的类型安全特性扩展到了API层,为开发者提供了从数据库到API的一致开发体验。通过简单的配置,开发者可以获得强大的过滤能力,同时保持代码的类型安全和可维护性。
这项功能特别适合需要构建复杂查询接口的应用场景,能够显著减少样板代码的编写,提高开发效率。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考