查询和更新
搭建好项目开发环境后,我们准备创建我们的待办事项列表并进行查询。
创建待办事项
我们先在可测试示例中创建一个 Todo。 我们将以下代码添加到 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
,它应该是能通过测试的。
添加字段到表结构
正如你看到的,我们的 Todo 只有一个 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").
Values("in_progress", "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
),并且通过插入了两行数据到表中;即我们创建了两个任务到我们的 Todo list 中。
Add Edges To The Schema
Let’s say we want to design our todo list so that an item can depend on another item. Therefore, we’ll add a parent
edge to each Todo item, to get the item it depends on, and a back-reference edge named children
in order to get all items that depend on it.
Let’s change our schema again in todo/ent/schema/todo.go
:
func (Todo) Edges() []ent.Edge {
return []ent.Edge{
edge.To("parent", Todo.Type).
Unique().
From("children"),
}
}
After adding these edges, we need to run the code-generation as before:
go generate ./ent
Connect 2 Todos
We continue our edges example, by updating the 2 todo items we just created. We define that item-2 (“Add Tracing Example”) depends on item-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"
}
Query Todos
After connecting item-2 to item-1, we’re ready to start querying our todo list.
Query all todo items:
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"
}
Query all todo items that depend on other items:
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"
}
Query all todo items that don’t depend on other items and have items that depend on them:
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"
}
Query parent through its children:
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"
}