Skip to content

openpkgs/gorm-whr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gorm-whr

一个轻量、可扩展的 GORM 条件构建器,封装分页、过滤、动态查询、租户等常见操作,适用于中后台业务场景,提升查询逻辑的可读性与复用性。

你可以像积木一样组合各种查询条件,让 GORM 查询变得简单而优雅。

Features

  • 支持分页:Limit、Offset、Page 分页转换
  • 支持链式调用构建查询条件
  • 支持结构化过滤(map)、动态查询(SQL 条件)
  • 支持租户隔离(multi-tenant)
  • 支持自定义 GORM Clause 扩展
  • 支持序列化为 JSON(便于日志输出)

安装

go get github.com/openpkgs/gorm-where

快速开始

import (
    "context"
    "gorm.io/gorm"
    "github.com/openpkgs/gorm-where"
)

func ListUsers(db *gorm.DB) error {
    opts := where.NewWhere(
        where.WithQuery("id > ?", 100),
        where.WithFilter(map[any]any{"status": "active"}),
        where.WithPage(1, 20), // 等价于 limit=20 offset=0
    )

    var users []User
    return opts.Where(db).Find(&users).Error
}

Option 构造器一览

你可以使用以下构造器初始化 Options:

函数名 说明
WithOffset(offset int64) 设置偏移量
WithLimit(limit int64) 设置返回数量上限
WithPage(page, pageSize int) 页码分页(自动转换为 Offset + Limit)
WithFilter(map[any]any) 结构化筛选条件,如 {"status": 1}
WithQuery(query interface{}, args ...interface{}) 动态 SQL 条件
WithClauses(...clause.Expression) 添加 GORM Clause,如 OrderBy

也可使用链式风格:

opts := where.NewWhere().
    Q("created_at >= ?", "2024-01-01").
    F("type", "admin").
    P(2, 10). // page 2, size 10
    C(clause.OrderBy{Columns: []clause.OrderByColumn{{Column: clause.Column{Name: "created_at"}, Desc: true}}})

Filters vs Queries 的区别

  • F(...) / WithFilter(...):结构化查询,适合字段 = 值
  • Q(...) / WithQuery(...):SQL 片段形式,支持复杂条件,例如:范围、模糊、IN 等
opts := where.NewWhere().
    F("status", "online").                      // WHERE status = 'online'
    Q("age BETWEEN ? AND ?", 18, 30).           // AND age BETWEEN 18 AND 30
    Q("name LIKE ?", "%张%")                    // AND name LIKE '%张%'

租户隔离(Multi-Tenant)

// 注册租户键和获取函数(通常在初始化阶段)
where.RegisterTenant("tenant_id", func(ctx context.Context) string {
    return ctx.Value("tenantID").(string)
})

// 在查询中自动加上租户过滤
opts := where.NewWhere().T(ctx)
db = opts.Where(db)

等效 SQL:

WHERE tenant_id = 'your-tenant-id'

高级用法:链式构建 vs 函数式构建

链式构建(推荐):

opts := where.NewWhere().
    Q("id > ?", 100).
    F("type", "vip").
    L(10).O(0)

函数式构建:

opts := where.NewWhere(
    where.WithQuery("id > ?", 100),
    where.WithFilter(map[any]any{"type": "vip"}),
    where.WithLimit(10),
    where.WithOffset(0),
)

与 GORM 配合使用

var users []User

err := where.NewWhere().
    Q("score > ?", 80).
    F("active", true).
    L(5).
    Where(db).
    Find(&users).Error

测试建议

可通过以下方式验证构造逻辑是否符合预期:

db = opts.Where(db).Session(&gorm.Session{DryRun: true})
sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {
    return tx.Find(&[]User{})
})
fmt.Println(sql)

JSON 序列化支持(用于日志输出)

data, _ := json.Marshal(opts)
fmt.Println(string(data))

输出:

{
  "offset": 0,
  "limit": 10,
  "filters": {
    "status": "online"
  },
  "clauses": [],
  "queries": [
    {
      "Query": "id > ?",
      "Args": [100]
    }
  ]
}

自定义扩展建议

你可以在业务层封装自己的条件组合:

func ActiveUsers(page, size int) *where.Options {
    return where.NewWhere().
        F("status", "active").
        P(page, size)
}

Contributing

欢迎提 PR 或 Issue,扩展更多查询语法和特性。特别是支持:

  • 联表查询
  • 动态排序(封装 OrderBy)
  • 筛选器(字段类型 + 操作符自动组合)

Thanks

本项目灵感来源于项目中频繁重复的 GORM 查询封装需求,致力于让查询逻辑更清晰、可复用、更工程化。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages