The ORM component provides some commonly used conditional query methods, and the conditional methods support multiple data type inputs.

  1. func (m *Model) Where(where interface{}, args...interface{}) *Model
  2. func (m *Model) Wheref(format string, args ...interface{}) *Model
  3. func (m *Model) WherePri(where interface{}, args ...interface{}) *Model
  4. func (m *Model) WhereBetween(column string, min, max interface{}) *Model
  5. func (m *Model) WhereLike(column string, like interface{}) *Model
  6. func (m *Model) WhereIn(column string, in interface{}) *Model
  7. func (m *Model) WhereNull(columns ...string) *Model
  8. func (m *Model) WhereLT(column string, value interface{}) *Model
  9. func (m *Model) WhereLTE(column string, value interface{}) *Model
  10. func (m *Model) WhereGT(column string, value interface{}) *Model
  11. func (m *Model) WhereGTE(column string, value interface{}) *Model
  12. func (m *Model) WhereNotBetween(column string, min, max interface{}) *Model
  13. func (m *Model) WhereNotLike(column string, like interface{}) *Model
  14. func (m *Model) WhereNotIn(column string, in interface{}) *Model
  15. func (m *Model) WhereNotNull(columns ...string) *Model
  16. func (m *Model) WhereOr(where interface{}, args ...interface{}) *Model
  17. func (m *Model) WhereOrBetween(column string, min, max interface{}) *Model
  18. func (m *Model) WhereOrLike(column string, like interface{}) *Model
  19. func (m *Model) WhereOrIn(column string, in interface{}) *Model
  20. func (m *Model) WhereOrNull(columns ...string) *Model
  21. func (m *Model) WhereOrLT(column string, value interface{}) *Model
  22. func (m *Model) WhereOrLTE(column string, value interface{}) *Model
  23. func (m *Model) WhereOrGT(column string, value interface{}) *Model
  24. func (m *Model) WhereOrGTE(column string, value interface{}) *Model
  25. func (m *Model) WhereOrNotBetween(column string, min, max interface{}) *Model
  26. func (m *Model) WhereOrNotLike(column string, like interface{}) *Model
  27. func (m *Model) WhereOrNotIn(column string, in interface{}) *Model
  28. func (m *Model) WhereOrNotNull(columns ...string) *Model

Below, we provide a brief introduction to several commonly used methods; other conditional query methods are similar in usage.

Where/WhereOr Query Conditions

Introduction

These two methods are used to pass query condition parameters, and the supported parameters can be any string/map/slice/struct/*struct type.

It is recommended to use a string parameter method for Where condition parameters (using ? as a placeholder for preprocessing) because map/struct types as query parameters cannot guarantee order, and in some cases (the database may help you automatically optimize query indexes), the order of the database index and the order of your query condition has a certain relationship.

When using multiple Where methods to connect query conditions, the conditions are connected using And. In addition, when multiple query conditions exist, gdb will default to enclosing each condition in () brackets, allowing for friendly support for query condition grouping.

Example usage:

  1. // WHERE `uid`=1
  2. Where("uid=1")
  3. Where("uid", 1)
  4. Where("uid=?", 1)
  5. Where(g.Map{"uid" : 1})
  6. // WHERE `uid` <= 1000 AND `age` >= 18
  7. Where(g.Map{
  8. "uid <=" : 1000,
  9. "age >=" : 18,
  10. })
  11. // WHERE (`uid` <= 1000) AND (`age` >= 18)
  12. Where("uid <=?", 1000).Where("age >=?", 18)
  13. // WHERE `level`=1 OR `money`>=1000000
  14. Where("level=? OR money >=?", 1, 1000000)
  15. // WHERE (`level`=1) OR (`money`>=1000000)
  16. Where("level", 1).WhereOr("money >=", 1000000)
  17. // WHERE `uid` IN(1,2,3)
  18. Where("uid IN(?)", g.Slice{1,2,3})

Example using struct parameters, where the orm tag is used to specify the mapping relationship between struct attributes and table fields:

  1. type Condition struct{
  2. Sex int `orm:"sex"`
  3. Age int `orm:"age"`
  4. }
  5. Where(Condition{1, 18})
  6. // WHERE `sex`=1 AND `age`=18

Example Usage

Where + string, using string and preprocessing as condition parameters.

  1. // Query multiple records with Limit pagination
  2. // SELECT * FROM user WHERE uid>1 LIMIT 0,10
  3. g.Model("user").Where("uid > ?", 1).Limit(0, 10).All()
  4. // Using the Fields method to specify query fields
  5. // Default query is * when Fields method is not used to specify query fields
  6. // SELECT uid,name FROM user WHERE uid>1 LIMIT 0,10
  7. g.Model("user").Fields("uid,name").Where("uid > ?", 1).Limit(0, 10).All()
  8. // Supporting multiple Where condition parameter types
  9. // SELECT * FROM user WHERE uid=1 LIMIT 1
  10. g.Model("user").Where("uid=1").One()
  11. g.Model("user").Where("uid", 1).One()
  12. g.Model("user").Where("uid=?", 1).One()
  13. // SELECT * FROM user WHERE (uid=1) AND (name='john') LIMIT 1
  14. g.Model("user").Where("uid", 1).Where("name", "john").One()
  15. g.Model("user").Where("uid=?", 1).Where("name=?", "john").One()
  16. // SELECT * FROM user WHERE (uid=1) OR (name='john') LIMIT 1
  17. g.Model("user").Where("uid=?", 1).WhereOr("name=?", "john").One()

Where + slice, preprocessing parameters can be directly provided through the slice parameter.

  1. // SELECT * FROM user WHERE age>18 AND name like '%john%'
  2. g.Model("user").Where("age>? AND name like ?", g.Slice{18, "%john%"}).All()
  3. // SELECT * FROM user WHERE status=1
  4. g.Model("user").Where("status=?", g.Slice{1}).All()

Where + map, using any map type to pass condition parameters.

  1. // SELECT * FROM user WHERE uid=1 AND name='john' LIMIT 1
  2. g.Model("user").Where(g.Map{"uid" : 1, "name" : "john"}).One()
  3. // SELECT * FROM user WHERE uid=1 AND age>18 LIMIT 1
  4. g.Model("user").Where(g.Map{"uid" : 1, "age>" : 18}).One()

Where + struct/*struct, struct tags support orm/json, mapping properties to field names.

  1. type User struct {
  2. Id int `json:"uid"`
  3. UserName string `orm:"name"`
  4. }
  5. // SELECT * FROM user WHERE uid =1 AND name='john' LIMIT 1
  6. g.Model("user").Where(User{ Id : 1, UserName : "john"}).One()
  7. // SELECT * FROM user WHERE uid =1 LIMIT 1
  8. g.Model("user").Where(&User{ Id : 1}).One()

The query conditions above are relatively simple. Let’s look at a more complex query example.

  1. condition := g.Map{
  2. "title like ?" : "%Jiuzhai%",
  3. "online" : 1,
  4. "hits between ? and ?" : g.Slice{1, 10},
  5. "exp > 0" : nil,
  6. "category" : g.Slice{100, 200},
  7. }
  8. // SELECT * FROM article WHERE title like '%Jiuzhai%' AND online=1 AND hits between 1 and 10 AND exp > 0 AND category IN(100,200)
  9. g.Model("article").Where(condition).All()

Wheref Formatted Condition String

In some scenarios, entering a conditional statement with strings often requires the use of fmt.Sprintf to format the condition (note to use placeholders in the string instead of directly formatting the variable), so a convenient method combining Where+fmt.Sprintf, Wheref, is provided. Usage example:

  1. // WHERE score > 100 and status in('succeeded','completed')
  2. Wheref(`score > ? and status in (?)`, 100, g.Slice{"succeeded", "completed"})

WherePri Supports Primary Key Query Conditions

The WherePri method functions the same way as Where, but it provides intelligent recognition of table primary keys and is commonly used for convenient data queries based on primary keys. Suppose the primary key of the user table is uid, let’s see the difference between Where and WherePri:

  1. // WHERE `uid`=1
  2. Where("uid", 1)
  3. WherePri(1)
  4. // WHERE `uid` IN(1,2,3)
  5. Where("uid", g.Slice{1,2,3})
  6. WherePri(g.Slice{1,2,3})

As you can see, when using the WherePri method and the given parameter is a single basic type or a slice type, it will be recognized as the value of the primary key query condition.

WhereBuilder Complex Condition Combinations

WhereBuilder is used to generate complex Where conditions.

Object Creation

We can use the Builder method of Model to generate a WhereBuilder object. The method is defined as follows:

  1. // Builder creates and returns a WhereBuilder.
  2. func (m *Model) Builder() *WhereBuilder

Usage Example

  1. // SELECT * FROM `user` WHERE `id`=1 AND `address`="USA" AND (`status`="active" OR `status`="pending")
  2. m := g.Model("user")
  3. all, err := m.Where("id", 1).Where("address", "USA").Where(
  4. m.Builder().Where("status", "active").WhereOr("status", "pending"),
  5. ).All()

Note: 0=1 Condition Triggered by Empty Array Condition

Let’s look at an example:

SQL1:

  1. m := g.Model("auth")
  2. m.Where("status", g.Slice{"permitted", "inherited"}).Where("uid", 1).All()
  3. // SELECT * FROM `auth` WHERE (`status` IN('permitted','inherited')) AND (`uid`=1)

SQL2:

  1. m := g.Model("auth")
  2. m.Where("status", g.Slice{}).Where("uid", 1).All()
  3. // SELECT * FROM `auth` WHERE (0=1) AND (`uid`=1)

As you can see, when the given array condition is an empty array, the resulting SQL has a 0=1 invalid condition. Why is that?

When developers do not explicitly declare the intention to filter empty array conditions, ORM does not automatically filter empty array conditions to avoid program logic bypassing SQL restriction conditions, which could cause unpredictable business issues. If the developer determines that the SQL restriction condition can be filtered, they can explicitly call the OmitEmpty/OmitEmptyWhere methods to perform empty condition filtering, as shown below:

  1. m := g.Model("auth")
  2. m.Where("status", g.Slice{}).Where("uid", 1).OmitEmpty().All()
  3. // SELECT * FROM `auth` WHERE `uid`=1