CRUD API

  • Client and Tx objects used for interacting with the graph.
  • CRUD builders for each schema type. See CRUD for more info.
  • Entity object (Go struct) for each of the schema type.
  • Package containing constants and predicates used for interacting with the builders.
  • A migrate package for SQL dialects. See for more info.

MySQL

PostgreSQL

  1. package main
  2. import (
  3. "log"
  4. "<project>/ent"
  5. _ "github.com/lib/pq"
  6. )
  7. func main() {
  8. client, err := ent.Open("postgres","host=<host> port=<port> user=<user> dbname=<database> password=<pass>")
  9. if err != nil {
  10. log.Fatal(err)
  11. }
  12. defer client.Close()
  13. }

SQLite

  1. package main
  2. import (
  3. "log"
  4. "<project>/ent"
  5. _ "github.com/mattn/go-sqlite3"
  6. )
  7. func main() {
  8. client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
  9. if err != nil {
  10. log.Fatal(err)
  11. }
  12. defer client.Close()
  13. }

Gremlin (AWS Neptune)

  1. package main
  2. import (
  3. "log"
  4. "<project>/ent"
  5. )
  6. func main() {
  7. client, err := ent.Open("gremlin", "http://localhost:8182")
  8. if err != nil {
  9. log.Fatal(err)
  10. }
  11. }

Create An Entity

Save a user.

  1. a8m, err := client.User. // UserClient.
  2. Create(). // User create builder.
  3. SetName("a8m"). // Set field value.
  4. SetNillableAge(age). // Avoid nil checks.
  5. AddGroups(g1, g2). // Add many edges.
  6. SetSpouse(nati). // Set unique edge.
  7. Save(ctx) // Create and return.

SaveX a pet; Unlike Save, SaveX panics if an error occurs.

  1. pedro := client.Pet. // PetClient.
  2. Create(). // Pet create builder.
  3. SetName("pedro"). // Set field value.
  4. SaveX(ctx) // Create and return.

Create Many

Save a bulk of pets.

  1. names := []string{"pedro", "xabi", "layla"}
  2. bulk := make([]*ent.PetCreate, len(names))
  3. for i, name := range names {
  4. bulk[i] = client.Pet.Create().SetName(name).SetOwner(a8m)
  5. }
  6. pets, err := client.Pet.CreateBulk(bulk...).Save(ctx)

Update One

Update an entity that was returned from the database.

  1. a8m, err = a8m.Update(). // User update builder.
  2. RemoveGroup(g2). // Remove specific edge.
  3. ClearCard(). // Clear unique edge.
  4. SetAge(30). // Set field value
  5. Save(ctx) // Save and return.
  1. pedro, err := client.Pet. // PetClient.
  2. UpdateOneID(id). // Pet update builder.
  3. SetOwnerID(owner). // Set unique edge, using id.
  4. Save(ctx) // Save and return.

Update Many

Filter using predicates.

  1. n, err := client.User. // UserClient.
  2. Update(). // Pet update builder.
  3. Where( //
  4. user.HasFriendsWith( // UserHasFriendsWith (
  5. user.Or( // age = 20
  6. user.Age(20), // OR
  7. user.Age(30), // age = 30
  8. ) // )
  9. ), //
  10. ). //
  11. SetName("a8m"). // Set field name.
  12. Save(ctx) // exec and return.

Upsert One

Ent supports ) records using the sql/upsert feature-flag.

  1. err := client.User.
  2. Create().
  3. SetAge(30).
  4. SetName("Ariel").
  5. OnConflict().
  6. // Use the new values that were set on create.
  7. UpdateNewValues().
  8. Exec(ctx)
  9. id, err := client.User.
  10. Create().
  11. SetAge(30).
  12. SetName("Ariel").
  13. OnConflict().
  14. // Use the "age" that was set on create.
  15. UpdateAge().
  16. // Set a different "name" in case of conflict.
  17. SetName("Mashraki").
  18. ID(ctx)
  19. // Customize the UPDATE clause.
  20. err := client.User.
  21. Create().
  22. SetAge(30).
  23. SetName("Ariel").
  24. OnConflict().
  25. UpdateNewValues().
  26. // Override some of the fields with a custom update.
  27. Update(func(u *ent.UserUpsert) {
  28. u.SetAddress("localhost")
  29. u.AddCount(1)
  30. u.ClearPhone()
  31. }).
  32. Exec(ctx)

In PostgreSQL, the is required:

  1. // Setting the column names using the fluent API.
  2. err := client.User.
  3. Create().
  4. SetName("Ariel").
  5. OnConflictColumns(user.FieldName).
  6. UpdateNewValues().
  7. Exec(ctx)
  8. // Setting the column names using the SQL API.
  9. err := client.User.
  10. Create().
  11. SetName("Ariel").
  12. OnConflict(
  13. sql.ConflictColumns(user.FieldName),
  14. ).
  15. UpdateNewValues().
  16. Exec(ctx)
  17. // Setting the constraint name using the SQL API.
  18. err := client.User.
  19. Create().
  20. OnConflict(
  21. sql.ConflictConstraint(constraint),
  22. ).
  23. UpdateNewValues().
  24. Exec(ctx)

In order to customize the executed statement, use the SQL API:

  1. id, err := client.User.
  2. Create().
  3. OnConflict(
  4. sql.ConflictColumns(...),
  5. sql.ConflictWhere(...),
  6. sql.UpdateWhere(...),
  7. ).
  8. u.SetAge(30)
  9. u.UpadteName()
  10. }).
  11. ID(ctx)
  12. // INSERT INTO "users" (...) VALUES (...) ON CONFLICT WHERE ... DO UPDATE SET ... WHERE ...
info" class="reference-link">info

Since the upsert API is implemented using the ON CONFLICT clause (and ON DUPLICATE KEY in MySQL), Ent executes only one statement to the database, and therefore, only create are applied for such operations.

Upsert Many

  1. err := client.User. // UserClient
  2. CreateBulk(builders...). // User bulk create.
  3. OnConflict(). // User bulk upsert.
  4. UpdateNewValues(). // Use the values that were set on create in case of conflict.
  5. Exec(ctx) // Execute the statement.

Get all users with followers.

  1. users, err := client.User. // UserClient.
  2. Query(). // User query builder.
  3. Where(user.HasFollowers()). // filter only users with followers.
  4. All(ctx) // query and return.

Get all followers of a specific user; Start the traversal from a node in the graph.

  1. users, err := a8m.
  2. QueryFollowers().
  3. All(ctx)

Get all pets of the followers of a user.

  1. users, err := a8m.
  2. QueryFollowers().
  3. QueryPets().
  4. All(ctx)

More advance traversals can be found in the .

Field Selection

Get all pet names.

  1. names, err := client.Pet.
  2. Query().
  3. Unique(true).
  4. Select(pet.FieldName).
  5. Strings(ctx)

Select partial objects and partial associations.gs Get all pets and their owners, but select and fill only the ID and Name fields.

  1. pets, err := client.Pet.
  2. Query().
  3. Select(pet.FieldName).
  4. WithOwner(func (q *ent.UserQuery) {
  5. q.Select(user.FieldName)
  6. }).
  7. All(ctx)

Scan all pet names and ages to custom struct.

  1. var v []struct {
  2. Age int `json:"age"`
  3. Name string `json:"name"`
  4. }
  5. err := client.Pet.
  6. Query().
  7. Select(pet.FieldAge, pet.FieldName).
  8. Scan(ctx, &v)
  9. if err != nil {
  10. log.Fatal(err)
  11. }

Update an entity and return a partial of it.

  1. pedro, err := client.Pet.
  2. UpdateOneID(id).
  3. SetAge(9).
  4. SetName("pedro").
  5. // Select allows selecting one or more fields (columns) of the returned entity.
  6. // The default is selecting all fields defined in the entity schema.
  7. Select(pet.FieldName).
  8. Save(ctx)

Delete One

Delete an entity.

  1. err := client.User.
  2. DeleteOne(a8m).
  3. Exec(ctx)

Delete by ID.

  1. err := client.User.
  2. DeleteOneID(id).
  3. Exec(ctx)

Delete Many

Delete using predicates.

  1. _, err := client.File.
  2. Delete().
  3. Where(file.UpdatedAtLT(date)).
  4. Exec(ctx)

Each generated node type has its own type of mutation. For example, all , share the same generated UserMutation object. However, all builder types implement the generic ent.Mutation interface.

For example, in order to write a generic code that apply a set of methods on both ent.UserCreate and ent.UserUpdate, use the UserMutation object:

  1. func Do() {
  2. creator := client.User.Create()
  3. SetAgeName(creator.Mutation())
  4. updater := client.User.UpdateOneID(id)
  5. SetAgeName(updater.Mutation())
  6. }
  7. // SetAgeName sets the age and the name for any mutation.
  8. func SetAgeName(m *ent.UserMutation) {
  9. m.SetAge(32)
  10. }

In some cases, you want to apply a set of methods on multiple types. For cases like this, either use the generic interface, or create your own interface.