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