mirror of
https://github.com/ent/ent.git
synced 2026-05-24 09:31:56 +03:00
ent/doc: continue getting-started section
Reviewed By: noamsch Differential Revision: D16709043 fbshipit-source-id: 75715e026a36cbea5e67866c73a6b6ed660f0546
This commit is contained in:
committed by
Facebook Github Bot
parent
7c84a20f2e
commit
be1d86b3b3
200
doc/md/doc1.md
200
doc/md/doc1.md
@@ -4,7 +4,7 @@ title: Quick Introduction
|
||||
sidebar_label: Quick Introduction
|
||||
---
|
||||
|
||||
`ent` is a simple, yet powerful ORM framework for Go built with the following principles:
|
||||
`ent` is a simple, yet powerful entity framework for Go built with the following principles:
|
||||
- Defining your schema as code.
|
||||
- Static typing first based on code generation.
|
||||
- Make the work with graph-like data in Go easier.
|
||||
@@ -166,7 +166,8 @@ func Query(ctx context.Context, client *ent.Client) (*ent.User, error) {
|
||||
u, err := client.User.
|
||||
Query().
|
||||
Where(user.NameEQ("a8m")).
|
||||
// `Only` fails if more than 1 user returned.
|
||||
// `Only` fails if no user found,
|
||||
// or more than 1 user returned.
|
||||
Only(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Error("failed querying user: %v", err)
|
||||
@@ -177,10 +178,197 @@ func Query(ctx context.Context, client *ent.Client) (*ent.User, error) {
|
||||
```
|
||||
|
||||
|
||||
## Placeholder 1
|
||||
## Add Your First Edge (Relation)
|
||||
In this part of the tutorial, we want to declare an edge to another entity in the schema.
|
||||
Let's create 2 additional entities named `Car` and `Group` with a few fields. We use `entc`
|
||||
to generate the initial schema:
|
||||
|
||||
Placeholder 1
|
||||
```console
|
||||
$ entc init Car Group
|
||||
```
|
||||
|
||||
## Placeholder 2
|
||||
And then, we add the rest of the fields manually:
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
Placeholder 2
|
||||
"github.com/facebookincubator/ent"
|
||||
"github.com/facebookincubator/ent/field"
|
||||
)
|
||||
|
||||
// Fields of the Car.
|
||||
func (Car) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.String("model"),
|
||||
field.Time("registered_at"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fields of the Group.
|
||||
func (Group) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.String("name").
|
||||
// regexp validation for group name.
|
||||
Match(regexp.MustCompile("[a-zA-Z_]+$")),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's define our first relation. An edge from `User` to `Car` defining that a user
|
||||
can have 1 or more cars, but a car has only one owner (one-to-many relation).
|
||||
|
||||

|
||||
|
||||
Let's add the `"cars"` edge to the `User` schema, and run `entc generate ./ent/schema`:
|
||||
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/facebookincubator/ent"
|
||||
"github.com/facebookincubator/ent/edge"
|
||||
)
|
||||
|
||||
// Edges of the User.
|
||||
func (User) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.To("cars", Car.Type),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We continue our example, by creating 2 cars, and add them to a user.
|
||||
```go
|
||||
func Do(ctx context.Context, client *ent.Client) error {
|
||||
// creating new car with model "Tesla".
|
||||
tesla, err := client.Car.
|
||||
Create().
|
||||
SetModel("Tesla").
|
||||
SetRegisteredAt(time.Now()).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed creating car: %v", err)
|
||||
}
|
||||
|
||||
// creating new car with model "Ford".
|
||||
ford, err := client.Car.
|
||||
Create().
|
||||
SetModel("Ford").
|
||||
SetRegisteredAt(time.Now()).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed creating car: %v", err)
|
||||
}
|
||||
log.Println("car was created: %v", ford)
|
||||
|
||||
// create a new user, and add it the 2 cars.
|
||||
a8m, err := client.User.
|
||||
Create().
|
||||
SetAge(30).
|
||||
SetName("a8m").
|
||||
AddCars(tesla, ford).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed creating user: %v", err)
|
||||
}
|
||||
log.Println("user was created: %v", a8m)
|
||||
}
|
||||
```
|
||||
But, what about querying the "cars" edge? Here's how we do it:
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
"<project>/ent"
|
||||
"<project>/ent/car"
|
||||
)
|
||||
|
||||
func Do(ctx context.Context, client *ent.Client) error {
|
||||
// <continuation of the code block above>
|
||||
// ...
|
||||
|
||||
cars, err := a8m.QueryCars().All(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed querying user cars: %v", err)
|
||||
}
|
||||
log.Println(cars...)
|
||||
|
||||
// what about filtering specific cars.
|
||||
ford, err := a8m.QueryCars().
|
||||
Where(car.NameEQ("Ford")).
|
||||
Only(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed querying user cars: %v", err)
|
||||
}
|
||||
log.Println(ford)
|
||||
}
|
||||
```
|
||||
|
||||
## Add Your First Inverse Edge (BackRef)
|
||||
Assume we have a `Car` object and we want to get its owner; The user that this car belongs to.
|
||||
For this, we have another type of edge called "inverse edge" that is defined using the `edge.From`
|
||||
function.
|
||||
|
||||

|
||||
|
||||
The new edge created in the diagram above is transparent, to emphasis that we don't create another
|
||||
edge in the database, and it is just a back-reference to the real edge.
|
||||
|
||||
Let's add an inverse edge named `"owner"` to the `Car` schema, reference it to the `"cars"` edge
|
||||
in the `User` schema, and run `entc generate ./ent/schema`.
|
||||
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/facebookincubator/ent"
|
||||
"github.com/facebookincubator/ent/edge"
|
||||
)
|
||||
|
||||
// Edges of the Car.
|
||||
func (Car) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
// create an inverse-edge called "owner" of type `User`
|
||||
// and reference it to the "cars" edge (in User schema)
|
||||
// explicitly using the `Ref` method.
|
||||
edge.From("owner", User.Type).
|
||||
Ref("cars").
|
||||
// setting the edge to unique, ensure
|
||||
// that a car can have only one owner.
|
||||
Unique(),
|
||||
}
|
||||
}
|
||||
```
|
||||
We'll continue the user/cars example above by querying the inverse edge.
|
||||
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
"<project>/ent"
|
||||
)
|
||||
|
||||
func Do(ctx context.Context, client *ent.Client) error {
|
||||
// <continuation of the code block above>
|
||||
// ...
|
||||
|
||||
cars, err := a8m.QueryCars().All(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed querying user cars: %v", err)
|
||||
}
|
||||
|
||||
// query the inverse edge.
|
||||
for _, car := range cars {
|
||||
owner, err := car.QueryOwner().Only(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed querying car %q owner: %v", car.Model, err)
|
||||
}
|
||||
log.Printf("car %q owner: %q", car.Model, owner.Name)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Create Your Second Edge
|
||||
|
||||
TODO: User/Group example.
|
||||
|
||||
Reference in New Issue
Block a user