beego中分页排序需用queryseter链式调用limit、offset、orderby,校验page≥1防offset为负,count()获取总数时复用filter条件避免n+1。

在Beego框架中实现分页查询和排序,需要结合ORM的QuerySeter接口与Limit、Offset、OrderBy等方法组合使用,避免手动拼SQL或重复加载全部数据到内存。
准备分页查询基础结构
先定义一个接收分页参数的结构体,包含Page、PageSize、SortField、SortOrder字段。Page从1开始计数,PageSize默认设为20,SortField为空时默认按ID降序,SortOrder只接受"asc"或"desc",其他值将被忽略。
在控制器中解析请求参数:c.GetInt("page", 1) → c.GetInt("pagesize", 20) → c.GetString("sortfield") → c.GetString("sortorder")。
计算offset = (page - 1) * pagesize,这个值必须是非负整数,【若page小于1会导致offset为负,QuerySeter会报错】。
执行带排序的分页查询
方法一:使用QuerySeter链式调用
先获取QuerySeter对象:o.QueryTable(&User{});然后依次调用OrderBy("-Id") → Limit(pagesize) → Offset(offset);最后用All()加载结果。OrderBy支持前缀"-"表示降序,"+"或不加表示升序,如OrderBy("Name", "-CreatedAt")可多字段排序。
方法二:先构造条件再追加排序与分页
o.QueryTable(&User{}).Filter("Status", 1).OrderBy("-UpdatedAt").Limit(pagesize, offset);注意Limit(a, b)中a是数量、b是偏移量,和MySQL LIMIT b,a顺序相反,【写反会导致取到错误的数据块】。
获取总记录数以支持前端分页控件
第一步:复用相同查询条件获取总数
使用同样的Filter条件(如Filter("Status", 1)),但去掉OrderBy和Limit/Offset,直接调用Count()方法。
第二步:避免N+1问题
不要在分页查询后对结果集遍历调用GetById,Count()是独立的一次COUNT(*)查询,和All()互不影响。如果Filter条件复杂,建议把条件逻辑封装成函数,确保Count和All使用的条件完全一致。
第三步:组装返回结构
将All()查出的[]*User、总数、当前页、每页条数、总页数((total + pagesize - 1) / pagesize)一并写入JSON响应。











