我正在尝试用Go语言构建一个API,它允许用户在3个主要点上搜索以找到"工作"。
- 一个文本查询-简单的
LIKE
对某些字段,例如。标题、描述 - Location -查看连接表
job_location
- Skill - look in join table
job_skill
如果用户没有提供任何这些,则默认返回表中的所有作业。我觉得我的问题是我所采取的方法是不可扩展的。有3个参数,因此用户可以提供的有9种可能的组合。如果我要加上第四个,我将需要覆盖16!searh组合。
这是我在控制器中的内容:
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
}