I'm using golang, go_reform, PostgreSQL. What i want to do is a REST search utility, and all went fine until I faced with conditional search query. "Conditional" here means I have 10 columns in a table to search in, and there may be ton of combinations so I can't handle them all separately. What i need is a query builder, but I have no understanding how can I implement this in Go. For now I have an idea like this, but it seems not really efficient
type Query struct {
Id *int64
FirstName *string
MiddleName *string
LastName *string
AreaId *int64
Birthday *time.Time
}
func (table *Query) Find() (*User) {
if table.Id != nil {
idstr := fmt.Sprintf("WHERE Id = %d AND ", table.Id)
}
else idstr := "WHERE "
}
if table.FirstName != "" {
firststr := fmt.Sprintf("FirstName = %s AND", table.FirstName)
}
else firststr := ""
}//and so on
That feels really awkward so I'm wondering is there any better way to determine the fields that came to the Find()
and build a SQL query based on this. (Actually it's coming in JSON and binding to Query
struct, so maybe there is a way without struct). There also may be SQL workarounds, but I think it would be more efficient to build query without all possible columns.
EDIT: By the way, making my Google search query more accurate, i found a bunch of things related to my problem, probably i will try to use it now. For those who interested too: old go playground example
Making dynamic SQL queries to a MySQL DB
gorp package (snippets thing sounds very promising)
So, I found the solution. Big thanks to Cerise Limón, whose code fits perfectly for me.
The solution I ended up with
Controller
func Find(c echo.Context) (err error) {
model := &models.Query{}
if err = c.Bind(model); err != nil {
return c.JSON(http.StatusInternalServerError, u.Message(false, "Bad request"))
}
resp := model.Find()
return c.JSON(http.StatusOK, resp)
Model
type Query map[string]interface{}
func (model Query) Find() (Query) {
var values []interface{}
var where []string
for k, v := range model {
values = append(values, v)
//MySQL Way: where = append(where, fmt.Sprintf("%s = ?", k))
where = append(where, fmt.Sprintf(`"%s" = %s`,k, "$" + strconv.Itoa(len(values))))
}
string := ("SELECT name FROM users WHERE " + strings.Join(where, " AND "))
//for testing purposes i didn't ran actual query, just print it in the console and returned JSON back
fmt.Println(string)
return model
}
Update: for PostgreSQL users (thanks to @mkopriva and his playground example), I'm able to have this placeholder thing working right on PostgreSQL
In orm GORM
,we do it like
if con1 {
db.Where("con1 =?", con1Flag)
}
If the orm you write yoursefl, I suggest change into gorm.Or you can refer to the orm you're using ,whether it has the same ussage like code above. If you're coding yourself, do it whatever you like. If you'r working in group, I guess using a mature orm is much better
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With