作用域允许你复用通用的逻辑,这种共享逻辑需要定义为类型func(*gorm.DB) *gorm.DB

查询

Scope 查询示例:

  1. func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
  2. return db.Where("amount > ?", 1000)
  3. }
  4. func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
  5. return db.Where("pay_mode_sign = ?", "C")
  6. }
  7. func PaidWithCod(db *gorm.DB) *gorm.DB {
  8. return db.Where("pay_mode_sign = ?", "C")
  9. }
  10. func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
  11. return func (db *gorm.DB) *gorm.DB {
  12. return db.Where("status IN (?)", status)
  13. }
  14. }
  15. db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
  16. // 查找所有金额大于 1000 的信用卡订单
  17. db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
  18. // 查找所有金额大于 1000 的 COD 订单
  19. db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
  20. // 查找所有金额大于1000 的已付款或已发货订单

分页

  1. func Paginate(r *http.Request) func(db *gorm.DB) *gorm.DB {
  2. return func (db *gorm.DB) *gorm.DB {
  3. q := r.URL.Query()
  4. page, _ := strconv.Atoi(q.Get("page"))
  5. if page == 0 {
  6. page = 1
  7. }
  8. pageSize, _ := strconv.Atoi(q.Get("page_size"))
  9. switch {
  10. case pageSize > 100:
  11. pageSize = 100
  12. case pageSize <= 0:
  13. pageSize = 10
  14. }
  15. offset := (page - 1) * pageSize
  16. return db.Offset(offset).Limit(pageSize)
  17. }
  18. }
  19. db.Scopes(Paginate(r)).Find(&users)
  20. db.Scopes(Paginate(r)).Find(&articles)

动态表

使用 Scopes 来动态指定查询的表

  1. func TableOfYear(user *User, year int) func(db *gorm.DB) *gorm.DB {
  2. return func(db *gorm.DB) *gorm.DB {
  3. tableName := user.TableName() + strconv.Itoa(year)
  4. return db.Table(tableName)
  5. }
  6. }
  7. DB.Scopes(TableOfYear(user, 2019)).Find(&users)
  8. // SELECT * FROM users_2019;
  9. DB.Scopes(TableOfYear(user, 2020)).Find(&users)
  10. // SELECT * FROM users_2020;
  11. // Table form different database
  12. func TableOfOrg(user *User, dbName string) func(db *gorm.DB) *gorm.DB {
  13. return func(db *gorm.DB) *gorm.DB {
  14. tableName := dbName + "." + user.TableName()
  15. return db.Table(tableName)
  16. }
  17. }
  18. DB.Scopes(TableOfOrg(user, "org1")).Find(&users)
  19. // SELECT * FROM org1.users;
  20. DB.Scopes(TableOfOrg(user, "org2")).Find(&users)
  21. // SELECT * FROM org2.users;

更新

Scope 更新、删除示例:

  1. func CurOrganization(r *http.Request) func(db *gorm.DB) *gorm.DB {
  2. return func (db *gorm.DB) *gorm.DB {
  3. org := r.Query("org")
  4. if org != "" {
  5. var organization Organization
  6. if db.Session(&Session{}).First(&organization, "name = ?", org).Error == nil {
  7. return db.Where("org_id = ?", organization.ID)
  8. }
  9. }
  10. db.AddError("invalid organization")
  11. return db
  12. }
  13. }
  14. db.Model(&article).Scopes(CurOrganization(r)).Update("Name", "name 1")
  15. // UPDATE articles SET name = "name 1" WHERE org_id = 111
  16. db.Scopes(CurOrganization(r)).Delete(&Article{})
  17. // DELETE FROM articles WHERE org_id = 111