一个轻量、可扩展的 GORM 条件构建器,封装分页、过滤、动态查询、租户等常见操作,适用于中后台业务场景,提升查询逻辑的可读性与复用性。
你可以像积木一样组合各种查询条件,让 GORM 查询变得简单而优雅。
- 支持分页:Limit、Offset、Page 分页转换
- 支持链式调用构建查询条件
- 支持结构化过滤(map)、动态查询(SQL 条件)
- 支持租户隔离(multi-tenant)
- 支持自定义 GORM Clause 扩展
- 支持序列化为 JSON(便于日志输出)
go get github.com/openpkgs/gorm-whereimport (
"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
}你可以使用以下构造器初始化 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}}})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 '%张%'// 注册租户键和获取函数(通常在初始化阶段)
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'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),
)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)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)
}欢迎提 PR 或 Issue,扩展更多查询语法和特性。特别是支持:
- 联表查询
- 动态排序(封装 OrderBy)
- 筛选器(字段类型 + 操作符自动组合)
本项目灵感来源于项目中频繁重复的 GORM 查询封装需求,致力于让查询逻辑更清晰、可复用、更工程化。