跳到主要内容

查询和突变

设置完项目后,我们准备创建待办事项清单(Todo list)并查询它。

创建待办事项

让我们在测试示例中创建一个待办事项。我们向 example_test.go 中添加如下代码:

func Example_Todo() {
// ...
task1, err := client.Todo.Create().Save(ctx)
if err != nil {
log.Fatalf("failed creating a todo: %v", err)
}
fmt.Println(task1)
// Output:
// Todo(id=1)
}

运行 go test 应当成功通过。

向模式添加字段

如你所见,我们的待办事项只有 ID 因此很无趣。让我们在 todo/ent/schema/todo.go 中添加 多个字段来改进它:

func (Todo) Fields() []ent.Field {
return []ent.Field{
field.Text("text").
NotEmpty(),
field.Time("created_at").
Default(time.Now).
Immutable(),
field.Enum("status").
NamedValues(
"InProgress", "IN_PROGRESS",
"Completed", "COMPLETED",
).
Default("IN_PROGRESS"),
field.Int("priority").
Default(0),
}
}

添加完这些字段后,我们需要向之前那样运行代码生成:

go generate ./ent

你可能注意到了,除了 text 字段外其他所有字段在创建时都有一个默认值,text 字段值需要用户提供。 让我们修改 example_test.go 为如下内容:

func Example_Todo() {
// ...
task1, err := client.Todo.Create().SetText("Add GraphQL Example").Save(ctx)
if err != nil {
log.Fatalf("failed creating a todo: %v", err)
}
fmt.Printf("%d: %q\n", task1.ID, task1.Text)
task2, err := client.Todo.Create().SetText("Add Tracing Example").Save(ctx)
if err != nil {
log.Fatalf("failed creating a todo: %v", err)
}
fmt.Printf("%d: %q\n", task2.ID, task2.Text)
// Output:
// 1: "Add GraphQL Example"
// 2: "Add Tracing Example"
}

很好!我们创建了一个模式,它在数据库中有五列(idtextcreated_atstatuspriority), 并通过向表中插入两个记录实现在我们的待办事项清单中创建了两个条目。

tutorial-todo-create

向模式添加边

我们希望设计的待办事项中一个条目依赖于另外一个条目。 因此我们为每一个待办事项条目添加一个 parent 边,用于获取该条目的依赖, 并添加一个名为 children 的反向引用边,用来获取依赖于此条目的所有条目。

让我们再次修改 todo/ent/schema/todo.go

func (Todo) Edges() []ent.Edge {
return []ent.Edge{
edge.To("parent", Todo.Type).
Unique().
From("children"),
}
}

添加完这些边后,我们需向之前一样运行代码生成:

go generate ./ent

连接两个待办事项

我们继续边的示例 —— 更新我们刚创建的两个待办事项。 我们定义 待办事项-2(“添加追踪示例”) 依赖于 待办事项-1(“添加 GraphQL 示例”)。

tutorial-todo-create

func Example_Todo() {
// ...
if err := task2.Update().SetParent(task1).Exec(ctx); err != nil {
log.Fatalf("failed connecting todo2 to its parent: %v", err)
}
// Output:
// 1: "Add GraphQL Example"
// 2: "Add Tracing Example"
}

查询待办事项

连接 条目-2 到 条目-1 后,我们准备查询待办事项列表:

查询所有待办事项条目:

func Example_Todo() {
// ...

// Query all todo items.
items, err := client.Todo.Query().All(ctx)
if err != nil {
log.Fatalf("failed querying todos: %v", err)
}
for _, t := range items {
fmt.Printf("%d: %q\n", t.ID, t.Text)
}
// Output:
// 1: "Add GraphQL Example"
// 2: "Add Tracing Example"
}

查询所有依赖于其他条目的待办事项条目:

func Example_Todo() {
// ...

// Query all todo items that depend on other items.
items, err := client.Todo.Query().Where(todo.HasParent()).All(ctx)
if err != nil {
log.Fatalf("failed querying todos: %v", err)
}
for _, t := range items {
fmt.Printf("%d: %q\n", t.ID, t.Text)
}
// Output:
// 2: "Add Tracing Example"
}

查询所有不依赖于其他条目但有其他条目依赖于它的待办事项条目:

func Example_Todo() {
// ...

// Query all todo items that don't depend on other items and have items that depend them.
items, err := client.Todo.Query().
Where(
todo.Not(
todo.HasParent(),
),
todo.HasChildren(),
).
All(ctx)
if err != nil {
log.Fatalf("failed querying todos: %v", err)
}
for _, t := range items {
fmt.Printf("%d: %q\n", t.ID, t.Text)
}
// Output:
// 1: "Add GraphQL Example"
}

通过子条目查询父条目:

func Example_Todo() {
// ...

// Get a parent item through its children and expect the
// query to return exactly one item.
parent, err := client.Todo.Query(). // Query all todos.
Where(todo.HasParent()). // Filter only those with parents.
QueryParent(). // Continue traversals to the parents.
Only(ctx) // Expect exactly one item.
if err != nil {
log.Fatalf("failed querying todos: %v", err)
}
fmt.Printf("%d: %q\n", parent.ID, parent.Text)
// Output:
// 1: "Add GraphQL Example"
}