Gorm scope 實現分頁
Gorm 是一個非常棒的 ORM。今天,我將向您展示如何使用 Gorm Scopes 創建分頁。
Scopes 可以實現一些邏輯的複用,這些邏輯需要定義爲如下格式:
func(*gorm.DB) *gorm.DB
首先創建一個 Pagination 結構體:
type Pagination struct {
PageSize int `json:"pageSize,omitempty" form:"pageSize"`
PageIndex int `json:"pageIndex,omitempty" form:"pageIndex"`
Sort string `json:"sort,omitempty" form:"sort"`
TotalRows int64 `json:"total_rows"`
TotalPages int `json:"total_pages"`
Rows interface{} `json:"rows"`
}
func (p *Pagination) GetOffset() int {
return (p.GetPage() - 1) * p.GetLimit()
}
func (p *Pagination) GetLimit() int {
if p.PageSize == 0 {
p.PageSize = 10
}
return p.PageSize
}
func (p *Pagination) GetPage() int {
if p.PageIndex == 0 {
p.PageIndex = 1
}
return p.PageIndex
}
func (p *Pagination) GetSort() string {
if p.Sort == "" {
p.Sort = "Id desc"
}
return p.Sort
}
然後創建 Gorm Scope。
func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
var totalRows int64
db.Model(value).Count(&totalRows)
pagination.TotalRows = totalRows
totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.Limit)))
pagination.TotalPages = totalPages
return func(db *gorm.DB) *gorm.DB {
return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())
}
}
然後將 Gorm scope 用在你的代碼中使用,如下所示:
package pagination
import (
"log"
"math"
"awesomeProject/pkg"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type CategoryGorm struct {
db *gorm.DB
}
func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
var totalRows int64
db.Model(value).Count(&totalRows)
pagination.TotalRows = totalRows
totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.PageSize)))
pagination.TotalPages = totalPages
return func(db *gorm.DB) *gorm.DB {
return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())
}
}
type Category struct {
Id int `json:"id"`
Type string `json:"type"`
}
func Server() {
db, err := gorm.Open(sqlite.Open("category.db"), &gorm.Config{})
if err != nil {
panic(err)
}
err = db.AutoMigrate(&Category{})
if err != nil {
panic(err)
}
c := CategoryGorm{db: db}
var engine = gin.Default()
engine.POST("/api/v1/category", c.AddCategory)
engine.GET("/api/v1/category", c.CategoryList)
panic(engine.Run(":9000"))
}
func (g CategoryGorm) AddCategory(c *gin.Context) {
var req Category
err := c.Bind(&req)
if err != nil {
log.Printf("parameters err for: %s", err.Error())
}
err = g.db.Model(&Category{}).Create(&req).Error
if err != nil {
log.Printf("insert category into db failed for: %s", err)
return
}
c.JSON(200, "success")
}
func (cg *CategoryGorm) CategoryList(c *gin.Context) {
var req pkg.Pagination
err := c.Bind(&req)
if err != nil {
log.Printf("parameters error %s", err)
return
}
list, err := cg.List(req)
if err != nil {
log.Printf("query category list failed for: %s", err)
}
c.JSON(200, list)
}
func (cg *CategoryGorm) List(pagination pkg.Pagination) (*pkg.Pagination, error) {
var categories []*Category
cg.db.Scopes(paginate(categories, &pagination, cg.db)).Find(&categories)
pagination.Rows = categories
return &pagination, nil
}
這裏只是爲了演示分頁效果,使用簡單的 demo 來完成。我們的代碼裏面用了 sqlite 數據庫,無需安裝只需要本地創建文件即可。
運行以上代碼,首先我們調用以下 POST 請求創建多個數據庫 category 對象供查詢:
接着調用以下分頁查詢看看效果:
http://localhost:9000/api/v1/category?pageIndex=1&pageSize=3
輸出:
{
"pageSize": 3,
"pageIndex": 1,
"sort": "Id desc",
"total_rows": 7,
"total_pages": 3,
"rows": [
{
"id": 8,
"type": "desk"
},
{
"id": 7,
"type": "joy"
},
{
"id": 6,
"type": "hat"
}
]
}
達到分頁效果。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Cyu4ScVFbXUeTuy_QKWhtg