Paging And Ordering

Limit

Limit limits the query result to n entities.

  1. users, err := client.User.
  2. Query().
  3. Limit(n).
  4. All(ctx)

Offset

Offset sets the first node to return from the query.

  1. users, err := client.User.
  2. Query().
  3. Offset(10).
  4. All(ctx)

Ordering

Order returns the entities sorted by the values of one or more fields. Note that, an error is returned if the given fields are not valid columns or foreign-keys.

  1. users, err := client.User.Query().
  2. Order(ent.Asc(user.FieldName)).
  3. All(ctx)

Starting with version v0.12.0, Ent generates type-safe ordering functions for fields and edges. The following example demonstrates how to use these generated functions:

  1. // Get all users sorted by their name (and nickname) in ascending order.
  2. users, err := client.User.Query().
  3. Order(
  4. user.ByName(),
  5. user.ByNickname(),
  6. ).
  7. All(ctx)
  8. // Get all users sorted by their nickname in descending order.
  9. users, err := client.User.Query().
  10. Order(
  11. user.ByNickname(
  12. sql.OrderDesc(),
  13. ),
  14. ).
  15. All(ctx)

Order By Edge Count

Order can also be used to sort entities based on the number of edges they have. For example, the following query returns all users sorted by the number of posts they have:

  1. users, err := client.User.Query().
  2. Order(
  3. // Users without posts are sorted first.
  4. user.ByPostsCount(),
  5. ).
  6. All(ctx)
  7. users, err := client.User.Query().
  8. Order(
  9. // Users without posts are sorted last.
  10. user.ByPostsCount(
  11. sql.OrderDesc(),
  12. ),
  13. ).
  14. All(ctx)

Order By Edge Field

Entities can also be sorted by the value of an edge field. For example, the following query returns all posts sorted by their author’s name:

  1. // Posts are sorted by their author's name in ascending
  2. // order with NULLs first unless otherwise specified.
  3. posts, err := client.Post.Query().
  4. Order(
  5. post.ByAuthorField(user.FieldName),
  6. ).
  7. All(ctx)
  8. posts, err := client.Post.Query().
  9. Order(
  10. post.ByAuthorField(
  11. user.FieldName,
  12. sql.OrderDesc(),
  13. sql.OrderNullsFirst(),
  14. ),
  15. ).
  16. All(ctx)

Custom Edge Terms

The generated edge ordering functions support custom terms. For example, the following query returns all users sorted by the sum of their posts’ likes and views:

  1. // Ascending order.
  2. posts, err := client.User.Query().
  3. Order(
  4. user.ByPosts(
  5. sql.OrderBySum(post.FieldNumLikes),
  6. sql.OrderBySum(post.FieldNumViews),
  7. ),
  8. ).
  9. All(ctx)
  10. // Descending order.
  11. posts, err := client.User.Query().
  12. Order(
  13. user.ByPosts(
  14. sql.OrderBySum(
  15. post.FieldNumLikes,
  16. sql.OrderDesc(),
  17. ),
  18. sql.OrderBySum(
  19. post.FieldNumViews,
  20. sql.OrderDesc(),
  21. ),
  22. ),
  23. ).
  24. All(ctx)

Select Order Terms

Ordered terms like SUM() and COUNT() are not defined in the schema and thus do not exist on the generated entities. However, sometimes there is a need to retrieve their information in order to either display it to the user or implement cursor-based pagination. The Value method, defined on each entity, allows you to obtain the order value if it was selected in the query:

  1. // Define the alias for the order term.
  2. const as = "pets_count"
  3. // Query users sorted by the number of pets
  4. // they have and select the order term.
  5. users := client.User.Query().
  6. Order(
  7. user.ByPetsCount(
  8. sql.OrderDesc(),
  9. sql.OrderSelectAs(as),
  10. ),
  11. user.ByID(),
  12. ).
  13. AllX(ctx)
  14. // Retrieve the order term value.
  15. for _, u := range users {
  16. fmt.Println(u.Value(as))
  17. }

Custom Ordering

Custom ordering functions can be useful if you want to write your own storage-specific logic.

  1. names, err := client.Pet.Query().
  2. Order(func(s *sql.Selector) {
  3. // Logic goes here.
  4. }).
  5. Select(pet.FieldName).
  6. Strings(ctx)

Order by JSON fields

The sqljson package allows to easily sort data based on the value of a JSON object:

  • By Value
  • By Length
  • Descending
  1. users := client.User.Query().
  2. Order(
  3. sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
  4. ).
  5. AllX(ctx)
  1. users := client.User.Query().
  2. Order(
  3. sqljson.OrderLen(user.FieldData, sqljson.Path("key1", "key2")),
  4. ).
  5. AllX(ctx)
  1. users := client.User.Query().
  2. Order(
  3. sqljson.OrderValueDesc(user.FieldData, sqljson.Path("key1", "key2")),
  4. ).
  5. AllX(ctx)
  6. pets := client.Pet.Query().
  7. Order(
  8. sqljson.OrderLenDesc(pet.FieldData, sqljson.Path("key1", "key2")),
  9. ).
  10. AllX(ctx)

PostgreSQL limitation on ORDER BY expressions with SELECT DISTINCT

PostgreSQL does not support ORDER BY expressions with SELECT DISTINCT. Thus, the Unique modifier should be set to false. However, keep in mind that this may result in duplicate results when performing graph traversals.

  1. users := client.User.Query().
  2. Order(
  3. sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
  4. ).
  5. + Unique(false).
  6. AllX(ctx)