查询与变更
完成项目设置后,我们现在可以创建待办事项列表并进行查询了。
创建待办事项
让我们在可测试示例中创建一个待办事项。将以下代码添加到 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 字段外,所有字段在创建时都有默认值。让我们修改 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"
}
很好!我们在数据库中创建了一个包含 5 列(id、text、created_at、status、priority)的模式,并通过向表中插入 2 行数据在我们的待办事项列表中创建了 2 个条目。

向模式添加边
假设我们希望设计待办事项列表,使得一个事项可以依赖于另一个事项。因此,我们将在每个待办事项中添加一个 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("Add Tracing Example")依赖于事项 1("Add GraphQL Example")。

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"
}