mirror of
https://github.com/ent/ent.git
synced 2026-05-22 09:31:45 +03:00
Summary: Pull Request resolved: https://github.com/facebookexternal/fbc/pull/1338 Pull Request resolved: https://github.com/facebookincubator/ent/pull/14 Reviewed By: alexsn Differential Revision: D16890825 fbshipit-source-id: 656baaa73f5debab08c849b6b9639caeec2a8ef1
173 lines
4.5 KiB
Markdown
173 lines
4.5 KiB
Markdown
## Ent
|
|
|
|
> Note: if you edit this file, don't forget to update the [Wiki][wiki] as well.
|
|
|
|
### First Installation
|
|
|
|
If it is the first time you work with `entc`, you need to compile it manually,
|
|
since we don't have any official binary distribution.
|
|
|
|
```
|
|
cd fbsource/fbcode/github.com/facebookincubator/ent/entc/cmd/entc
|
|
go build
|
|
sudo mv entc /usr/local/bin
|
|
```
|
|
|
|
### Creating Schema
|
|
If you came here to see how to create your first schema, it's preferred to give `entc`
|
|
to do it for you in order to keep the same standard for all projects that use it.
|
|
Run the following (replace `User/Group` with your entities):
|
|
|
|
```
|
|
entc init User Group
|
|
```
|
|
|
|
The schema that was created has 2 methods: `User.Fields` and `User.Edges`. The first defines the fields/properties
|
|
of the entity in the graph, and the second defines the edges for other entities (or to itself) in the graph.
|
|
|
|
Here are a few examples that will help you to understand what field/edge to declare in your schema
|
|
```
|
|
type User struct{
|
|
ent.Schema
|
|
}
|
|
|
|
func (User) Fields() []ent.Field {
|
|
return []ent.Field{
|
|
// "age" defines a field of type int, with a positive validator.
|
|
// The validator is called on create or update on this field.
|
|
field.Int("age").
|
|
Positive(),
|
|
|
|
// "name" defines a field of type string, and overrides the standard
|
|
// tag for the generated entity.
|
|
field.String("name").
|
|
StructTag(`json:"first_name" graphql:"first_name"`),
|
|
|
|
// "last" defines a field of type string, with default (on creation) to "unknown",
|
|
// and 2 validators.
|
|
field.String("last").
|
|
Default("unknown").
|
|
Match(regexp.MustCompile("[a-zA-Z_]+$")).
|
|
Validate(func(s string) error {
|
|
if strings.ToLower(s) == s {
|
|
return errors.New("last name must begin with uppercase")
|
|
}
|
|
return nil
|
|
}),
|
|
}
|
|
}
|
|
|
|
func (User) Edges() []ent.Edge {
|
|
return []ent.Edge{
|
|
// "groups" defines an edge to the Group entity (also a schema in this package).
|
|
// The relation type for this edge is many-2-many.
|
|
edge.To("groups", Group.Type),
|
|
|
|
// "workplace" defines an edge from the Company entity (also a schema in this package).
|
|
// The relation type for this edge is many-2-one, and the owner of this edge, is the
|
|
// Company entity.
|
|
edge.From("workplace", Company.Type).Unique().Ref("employees"),
|
|
|
|
// "parent" defines an edge from a User to itself.
|
|
edge.To("parent", User.Type).Unique().From("children"),
|
|
}
|
|
}
|
|
```
|
|
|
|
### Code Generation
|
|
|
|
After running init, run the codegen on the directory the was created (`ent/schema`).
|
|
|
|
```
|
|
entc generate ./ent/schema
|
|
```
|
|
|
|
In addition to the "production" code, `entc` generates for you also an `example_test.go` file
|
|
with example for each ent in the graph.
|
|
|
|
### Working with the generated code
|
|
|
|
First, you need to create the `ent.Client` in order to interact with the different builders,
|
|
then, use this client to create, update, delete, or query entities.
|
|
|
|
```
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
|
|
"<project>/ent"
|
|
"<project>/ent/user"
|
|
"github.com/facebookincubator/ent/dialect/sql"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Backgorund()
|
|
drv, err := sql.Open("mysql", "root:pass@tcp(localhost:3306)/test?charset=utf8&parseTime=True")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer drv.Close()
|
|
client := ent.NewClient(drv)
|
|
|
|
// Create:
|
|
|
|
// `client.User` holds the `UserClient`, and `client.User.Create()` returns a new User creator.
|
|
a8m, err := client.User.
|
|
Create().
|
|
SetAge(30)
|
|
SetName("a8m").
|
|
Save(ctx)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
// If you want to ignore the error checks in the code, replace `Save` with `SaveX`.
|
|
|
|
// Delete:
|
|
|
|
// delete one.
|
|
client.User.DeleteOne(a8m).ExecX(ctx)
|
|
// delete all.
|
|
client.User.Delete().ExecX(ctx)
|
|
// delete with condition.
|
|
client.User.Delete().Where(user.Name("a8m")).ExecX(ctx)
|
|
|
|
// Update:
|
|
|
|
// add a user to a group.
|
|
a8m = client.User.UpdateOne(a8m).AddGroups(grp).SaveX(ctx)
|
|
// delete a user from a group.
|
|
a8m = client.User.UpdateOne(a8m).RemoveGroups(grp).SaveX(ctx)
|
|
// add user to all groups.
|
|
client.Group.Update().AddUsers(a8m).ExecX(ctx)
|
|
|
|
// Query:
|
|
|
|
// get all groups.
|
|
groups := client.Group.Query().AllX(ctx)
|
|
// get all groups of a specific user.
|
|
groups = a8m.QueryGroups().AllX(ctx)
|
|
// query by path.
|
|
users := client.Group.
|
|
Query().
|
|
Where(group.HasUsers(), group.NameHasPrefix("fb")).
|
|
QueryUsers().
|
|
AllX(ctx)
|
|
|
|
// Aggregation:
|
|
|
|
var v []struct{
|
|
Name string `json:"name"`
|
|
Count int `json:"count"`
|
|
}
|
|
client.User.
|
|
Query().
|
|
GroupBy(user.FieldName).
|
|
Aggregate(ent.Count()).
|
|
ScanX(&v)
|
|
}
|
|
```
|
|
|
|
|
|
[wiki]: https://our.internmc.facebook.com/intern/wiki/Facebook_Connectivity_(FBC)/Entity_Framework/
|