使用多个可选参数编​​写 API 端点

writing an API endpoint with multiple optional parameters

我正在尝试用 Go 构建一个 API,它允许用户搜索 3 个要点来找到“工作”。

如果用户未提供任何这些,则默认返回 table 中的所有作业。我觉得我的问题是我采用的方法不可扩展。有 3 个参数,因此用户可以提供约 9 种可能的组合。如果我要添加第四个,我需要覆盖 16 个!搜索组合。

这是我的控制器中的内容:

func (j *Jobs) List(c *client.Client, q string, l string, s string) error {

    // Return all jobs
    if q == "" && l == "" && s == "" {
        err := c.Database.Debug().Preload("Locations").Preload("Skills").Find(&j).Error //
        if err != nil {
            return err
        }
    }

    // Return based on query
    if q != "" && l == "" && s == "" {
        c.Database.Where("LOWER(title) like LOWER(?) OR LOWER(description) like LOWER(?)", "%"+q+"%", "%"+q+"%").Preload("Locations").Preload("Skills").Find(&j)
    }

    // return based on location
    if q == "" && l != "" && s == "" {
        c.Database.Preload("Skills").Preload("Locations").Joins("INNER JOIN job_location jl ON jl.job_id = jobs.id").Where("jl.location_name = ?", l).Find(&j)
    }

    // return based on skill
    if q == "" && l == "" && s != "" {
        c.Database.Preload("Skills").Preload("Locations").Joins("INNER JOIN job_skill js ON js.job_id = jobs.id").Where("js.skill_name = ?", s).Find(&j)
    }

    // return based on query + location
    if q != "" && l != "" && s == "" {
        c.Database.Preload("Locations").Preload("Skills").Joins("INNER JOIN job_location jl ON jl.job_id = jobs.id").Where("jl.location_name = ?", l).Where("LOWER(title) like LOWER(?) OR LOWER(description) like LOWER(?)", "%"+q+"%", "%"+q+"%").Find(&j)
    }

    // return based on query + skill
    if q != "" && l == "" && s != "" {
        c.Database.Preload("Locations").Preload("Skills").Joins("INNER JOIN job_skill js ON js.job_id = jobs.id").Where("js.skill_name = ?", s).Where("LOWER(title) like LOWER(?) OR LOWER(description) like LOWER(?)", "%"+q+"%", "%"+q+"%").Find(&j)
    }

    // return based on location + skill
    if q == "" && l != "" && s != "" {
        c.Database.Preload("Skills").Preload("Locations").Joins("INNER JOIN job_location jl ON jl.job_id = jobs.id").Joins("INNER JOIN job_skill js ON js.job_id = jobs.id").Where("jl.location_name = ?", l).Where("js.skill_name = ?", s).Find(&j)
    }

    // return based on query + skill + location
    if q != "" && l != "" && s != "" {
        c.Database.Preload("Locations").Preload("Skills").Joins("INNER JOIN job_location jl ON jl.job_id = jobs.id").Joins("INNER JOIN job_skill js ON js.job_id = jobs.id").Where("js.skill_name = ?", s).Where("jl.location_name = ?", l).Where("LOWER(title) like LOWER(?) OR LOWER(description) like LOWER(?)", "%"+q+"%", "%"+q+"%").Find(&j)
    }

    return nil
}

如您所见,只有 3 个参数,这是一个巨大的代码块。我可以通过哪些方法改进它并在添加字段时使其更易于管理。

您可以通过创建公共部分来构建查询,然后再向其中添加可选部分,如下所示:

func (j *Jobs) List(c *client.Client, q string, l string, s string) error {
    query := c.Database.Debug().Preload("Locations").Preload("Skills")
    // return based on query
    if q != "" {
        query = query.Where("LOWER(title) like LOWER(?) OR LOWER(description) like LOWER(?)", "%"+q+"%", "%"+q+"%")
    }

    // return based on location
    if l != "" {
        query = query.Joins("INNER JOIN job_location jl ON jl.job_id = jobs.id").Where("jl.location_name = ?", l)
    }

    // return based on skill
    if s != "" {
        query = query.Joins("INNER JOIN job_skill js ON js.job_id = jobs.id").Where("js.skill_name = ?", s)
    }

    // Return all jobs
    return query.Find(&j).Error
}