分页与排序
Limit
Limit 用于将查询结果限制为 n 个实体。
users, err := client.User.
Query().
Limit(n).
All(ctx)
Offset
Offset 设置从查询结果中返回的第一个节点的偏移量。
users, err := client.User.
Query().
Offset(10).
All(ctx)
排序
Order 用于按一个或多个字段的值对实体进行排序。注意,如果给定字段不是有效列或外键,将返回错误。
users, err := client.User.Query().
Order(ent.Asc(user.FieldName)).
All(ctx)
从 v0.12.0 版本开始,Ent 为字段和边生成类型安全的排序函数。以下示例演示了如何使用这些生成函数:
// 获取所有用户按姓名(和昵称)升序排序。
users, err := client.User.Query().
Order(
user.ByName(),
user.ByNickname(),
).
All(ctx)
// 获取所有用户按昵称降序排序。
users, err := client.User.Query().
Order(
user.ByNickname(
sql.OrderDesc(),
),
).
All(ctx)
按边数量排序
Order 也可用于根据实体拥有的边数量进行排序。例如,以下查询返回所有用户按其拥有的帖子数量排序:
users, err := client.User.Query().
Order(
// 没有帖子的用户排在前面。
user.ByPostsCount(),
).
All(ctx)
users, err := client.User.Query().
Order(
// 没有帖子的用户排在后面。
user.ByPostsCount(
sql.OrderDesc(),
),
).
All(ctx)
按边字段排序
实体也可以按边字段的值进行排序。例如,以下查询返回所有帖子按其作者姓名排序:
// 帖子按其作者姓名升序排序,
// 除非另有说明,NULL 值排在最前面。
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)
自定义边排序项
生成的边排序函数支持自定义项。例如,以下查询返回所有用户按其帖子的点赞数和浏览数之和排序:
// 升序排序。
posts, err := client.User.Query().
Order(
user.ByPosts(
sql.OrderBySum(post.FieldNumLikes),
sql.OrderBySum(post.FieldNumViews),
),
).
All(ctx)
// 降序排序。
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 方法允许您在查询中选择排序项后获取其值:
// 为排序项定义别名。
const as = "pets_count"
// 查询用户按其拥有的宠物数量排序,
// 并选择排序项。
users := client.User.Query().
Order(
user.ByPetsCount(
sql.OrderDesc(),
sql.OrderSelectAs(as),
),
user.ByID(),
).
AllX(ctx)
// 检索排序项的值。
for _, u := range users {
fmt.Println(u.Value(as))
}
自定义排序
如果您想编写自己的存储特定逻辑,自定义排序函数可能很有用。
names, err := client.Pet.Query().
Order(func(s *sql.Selector) {
// 此处编写逻辑。
}).
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)