使用多个可选参数编写 API 端点
writing an API endpoint with multiple optional parameters
我正在尝试用 Go 构建一个 API,它允许用户搜索 3 个要点来找到“工作”。
- 文本查询 - 对某些字段的简单
LIKE
,例如。标题、描述
- 位置 - 在加入中查找 table
job_location
- Skill - Looks in join table
job_skill
如果用户未提供任何这些,则默认返回 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
}
我正在尝试用 Go 构建一个 API,它允许用户搜索 3 个要点来找到“工作”。
- 文本查询 - 对某些字段的简单
LIKE
,例如。标题、描述 - 位置 - 在加入中查找 table
job_location
- Skill - Looks in join table
job_skill
如果用户未提供任何这些,则默认返回 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
}