分页和排序(Paging And Ordering)
数量限制(Limit)
Limit 限制查询的结果为 n 个实体。
users, err := client.User.
Query().
Limit(n).
All(ctx)
偏移(Offset)
Offset 设置查询结果的第一个节点。
users, err := client.User.
Query().
Offset(10).
All(ctx)
排序(Ordering)
Order 返回由一个或多个字段排序后的实体。注意,如果给定的字段或外键无效则会返回错误。
users, err := client.User.Query().
Order(ent.Asc(user.FieldName)).
All(ctx)
自 v0.12.0 版本开始,Ent 为字段和边生成类型安全的排序函数。下面的示例演示如何使用这些生成的函数:
// Get all users sorted by their name (and nickname) in ascending order.
users, err := client.User.Query().
Order(
user.ByName(),
user.ByNickname(),
).
All(ctx)
// Get all users sorted by their nickname in descending order.
users, err := client.User.Query().
Order(
user.ByNickname(
sql.OrderDesc(),
),
).
All(ctx)
以边的数量进行排序
Order 也可以用来基于拥有的边的数量对实体进行排序。例如,下面的查询返回以拥有文章(post)数量进行排序的所有用户(user)。
users, err := client.User.Query().
Order(
// Users without posts are sorted first.
user.ByPostsCount(),
).
All(ctx)
users, err := client.User.Query().
Order(
// Users without posts are sorted last.
user.ByPostsCount(
sql.OrderDesc(),
),
).
All(ctx)
以边字段进行排序
实体也可以按边字段进行排序。例如,下面的查询返回以作者(author)名字进行排序后的所有文章(post):
// Posts are sorted by their author's name in ascending
// order with NULLs first unless otherwise specified.
posts, err := client.Post.Query().
Order(
post.ByAuthorField(user.FieldName),
).
All(ctx)
posts, err := client.Post.Query().
Order(
post.ByAuthorField(
user.FieldName,
sql.OrderDesc(),
sql.OrderNullsFirst(),
),
).
All(ctx)
自定义边条件
生成的边排序函数支持自定义条件。例如,下面的查询返回以文章(post)点赞(like)和查看(view)总数进行排序的所有用户(user):
// Ascending order.
posts, err := client.User.Query().
Order(
user.ByPosts(
sql.OrderBySum(post.FieldNumLikes),
sql.OrderBySum(post.FieldNumViews),
),
).
All(ctx)
// Descending order.
posts, err := client.User.Query().
Order(
user.ByPosts(
sql.OrderBySum(
post.FieldNumLikes,
sql.OrderDesc(),
),
sql.OrderBySum(
post.FieldNumViews,
sql.OrderDesc(),
),
),
).
All(ctx)
选择排序条件
SUM() 和 COUNT() 等排序条件在模式中没有定义所以在生成的实体上也不存在。
但有时需要获取他们的信息来进行显示给用户或实现基于游标的分页。Value 在每个实体上都进行了定义,允许你在查询中获取选中的排序值:
// Define the alias for the order term.
const as = "pets_count"
// Query users sorted by the number of pets
// they have and select the order term.
users := client.User.Query().
Order(
user.ByPetsCount(
sql.OrderDesc(),
sql.OrderSelectAs(as),
),
user.ByID(),
).
AllX(ctx)
// Retrieve the order term value.
for _, u := range users {
fmt.Println(u.Value(as))
}
自定义排序
如果你想要写自己特定的存储逻辑那么自定义排序函数会很有用。
names, err := client.Pet.Query().
Order(func(s *sql.Selector) {
// Logic goes here.
}).
Select(pet.FieldName).
Strings(ctx)
以 JSON 字段排序
sqljson 包允许你基于 JSON 对象的值进行数据简单排序:
- 按值排序
- 按长度排序
- 倒序
users := client.User.Query().
Order(
sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
users := client.User.Query().
Order(
sqljson.OrderLen(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
users := client.User.Query().
Order(
sqljson.OrderValueDesc(user.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
pets := client.Pet.Query().
Order(
sqljson.OrderLenDesc(pet.FieldData, sqljson.Path("key1", "key2")),
).
AllX(ctx)
PostgreSQL 在具有 SELECT DISTINCT 的 ORDER BY 表达式的限制
PostgreSQL 不支持具有 SELECT DISTINCT 的 ORDER BY 表达式。因此,Unique 修改器应当被设置为 false。
但请记住,在执行图遍历时,这可能会导致重复结果。
users := client.User.Query().
Order(
sqljson.OrderValue(user.FieldData, sqljson.Path("key1", "key2")),
).
+ Unique(false).
AllX(ctx)