Golang中逐步构建GORM查询的方法

Golang中逐步构建GORM查询的方法 我正在尝试逐步构建查询,如果传递结构体(模型/模式),这似乎是成功的(使用gorm)。但由于我(可能)有超过100张表,它需要独立于结构体。因此,我传递接口如下:

func QueryBuilder(db *gorm.DB , model interface{},param schemas.Query) interface{}{
  db = BuildSelect(db , param.Select)
  db = BuildWhere(db , param.Where)
      // 到这里一切正常,但gorm报错,它需要一个切片或结构体。
  db = BuildWhereOr(db , param.Or).Find(&model)
  fmt.Println("after Build")
  return model
}

如何将结果返回到所需的结构体/模式中?非常感谢任何帮助或解决方案。


更多关于Golang中逐步构建GORM查询的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

我正在尝试逐步构建查询

基本上,我根据提供的输入逐步构建查询的不同部分。

更多关于Golang中逐步构建GORM查询的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Sibert:

你可以通过使用 JOIN、CTE 或子查询,将两步查询合并为一步。如果你创建一个示例并给出期望的输出,我可以给你一个例子。

这根本不是问题。我只是将一个结构体的引用传递给 gorm,它就正常工作了。非常感谢你的关注和帮助。

tanweershahzaad: 我如何才能以期望的结构/模式获取结果。非常感谢任何帮助或解决方案。

你可以使用 JOIN、CTE 或子查询,一步完成两步查询。如果你创建一个测试用例并给出期望的输出,我可以给你一个示例。

DB Fiddle - SQL Database Playground

DB Fiddle - SQL Database Playground

一个用于测试、调试和分享 SQL 代码片段的在线 SQL 数据库平台。

在Golang中逐步构建GORM查询而不依赖具体结构体,可以通过使用*gorm.DB的链式调用配合反射来实现。以下是解决方案:

import (
    "gorm.io/gorm"
    "reflect"
)

func QueryBuilder(db *gorm.DB, model interface{}, param schemas.Query) (interface{}, error) {
    // 创建模型的切片类型用于Find查询
    modelType := reflect.TypeOf(model)
    sliceType := reflect.SliceOf(modelType)
    resultSlice := reflect.New(sliceType).Interface()
    
    // 逐步构建查询
    db = BuildSelect(db, param.Select)
    db = BuildWhere(db, param.Where)
    db = BuildWhereOr(db, param.Or)
    
    // 执行查询
    if err := db.Find(resultSlice).Error; err != nil {
        return nil, err
    }
    
    return reflect.ValueOf(resultSlice).Elem().Interface(), nil
}

// 使用示例:
type User struct {
    ID   uint
    Name string
}

func main() {
    var users []User
    result, err := QueryBuilder(db, User{}, param)
    if err == nil {
        users = result.([]User)
    }
}

对于更通用的解决方案,可以使用interface{}接收结果:

func QueryBuilderGeneric(db *gorm.DB, model interface{}, param schemas.Query) (interface{}, error) {
    // 通过反射创建模型切片
    modelValue := reflect.ValueOf(model)
    if modelValue.Kind() == reflect.Ptr {
        modelValue = modelValue.Elem()
    }
    
    sliceType := reflect.SliceOf(modelValue.Type())
    resultSlice := reflect.New(sliceType).Interface()
    
    // 构建查询链
    query := db.Model(model)
    query = BuildSelect(query, param.Select)
    query = BuildWhere(query, param.Where)
    query = BuildWhereOr(query, param.Or)
    
    // 执行查询
    if err := query.Find(resultSlice).Error; err != nil {
        return nil, err
    }
    
    return reflect.ValueOf(resultSlice).Elem().Interface(), nil
}

如果需要在运行时动态确定模型类型:

func QueryBuilderByTableName(db *gorm.DB, tableName string, param schemas.Query) (*gorm.DB, error) {
    // 构建基础查询
    query := db.Table(tableName)
    
    // 应用查询条件
    query = BuildSelect(query, param.Select)
    query = BuildWhere(query, param.Where)
    query = BuildWhereOr(query, param.Or)
    
    return query, nil
}

// 使用方式:
query, err := QueryBuilderByTableName(db, "users", param)
if err == nil {
    var results []map[string]interface{}
    query.Find(&results)
}

对于返回map[string]interface{}格式的结果:

func QueryBuilderToMap(db *gorm.DB, model interface{}, param schemas.Query) ([]map[string]interface{}, error) {
    var results []map[string]interface{}
    
    db = BuildSelect(db, param.Select)
    db = BuildWhere(db, param.Where)
    db = BuildWhereOr(db, param.Or)
    
    if err := db.Model(model).Find(&results).Error; err != nil {
        return nil, err
    }
    
    return results, nil
}
回到顶部