1. 程式人生 > 其它 >(十)beeego模型之orm高階查詢

(十)beeego模型之orm高階查詢

針對業務比較複雜,涉及複雜的查詢條件的場景,beego orm為我們提供了QuerySeter 物件,用來組織複雜的查詢條件。

一、QuerySeter入門

因為QuerySeter是專門針對ORM的模型物件進行操作的,所以在使用QuerySeter之前必須先定義好模型。

1.1 表定義

模型(model)是跟表結構一一對應的,作為例子這裡先定義下表結構。

// 定義使用者表
CREATE TABLE `users` (
  `id` int(10) UNSIGNED NOT NULL COMMENT '自增ID',
  `username` varchar(30) NOT NULL COMMENT '賬號',
  `password` varchar(100) NOT NULL COMMENT '密碼',
  `city` varchar(50) DEFAULT NULL COMMENT '城市',
  `init_time` datetime DEFAULT NULL COMMENT '建立時間'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.2 模型定義

//定義User模型,繫結users表結構
type User struct {
	Id int
	Username string
	Password string
	City string
	// 駝峰式命名,會轉換成表字段名,表字段名使用蛇形命名風格,即用下劃線將單詞連線起來
    // 這裡對應資料庫表的init_time欄位名
	InitTime time.Time
}

// 定義模型表名
func (u *User) TableName() string {
	return "users"
}

1.3 QuerySeter例子

// 建立orm物件
o := orm.NewOrm()

// 獲取 QuerySeter 物件,並設定表名orders
qs := o.QueryTable("users")

// 定義儲存查詢結果的變數
var users []User

// 使用QuerySeter 物件構造查詢條件,並執行查詢。
num, err := qs.Filter("city", "shenzhen").  // 設定查詢條件
		Filter("init_time__gt", "2019-06-28 22:00:00"). // 設定查詢條件
		Limit(10). // 限制返回行數
		All(&users, "id", "username") // All 執行查詢,並且返回結果,這裡指定返回id和username欄位,結果儲存在users變數
// 上面程式碼的等價sql: SELECT T0.`id`, T0.`username` FROM `users` T0 WHERE T0.`city` = 'shenzhen' AND T0.`init_time` > '2019-06-28 22:00:00' LIMIT 10

if err != nil {
	panic(err)
}
fmt.Println("結果行數:", num)

二、QuerySeter查詢表示式

beego orm針對QuerySeter設定一套查詢表示式,用於編寫查詢條件。

提示:下面例子,使用Filter函式描述查詢表示式,實際上其他查詢函式也支援查詢表示式。

表示式格式1:

qs.Filter("id", 1) // 相當於條件 id = 1

表示式格式2:
使用雙下劃線 __ 作為分隔符,尾部連線操作符

qs.Filter("id__gt", 1) // 相當於條件 id > 1
qs.Filter("id__gte", 1) // 相當於條件 id >= 1
qs.Filter("id__lt", 1) // 相當於條件 id < 1
qs.Filter("id__lte", 1) // 相當於條件 id <= 1
qs.Filter("id__in", 1,2,3,4,5) // 相當於In語句 id in (1,2,3,4,5)

下面是支援的操作符:

  • exact / iexact 等於
  • contains / icontains 包含
  • gt / gte 大於 / 大於等於
  • lt / lte 小於 / 小於等於
  • startswith / istartswith 以…起始
  • endswith / iendswith 以…結束
  • in
  • isnull 後面以 i 開頭的表示:大小寫不敏感

例子:

qs.Filter("Username", "大錘") // 相當於條件 name = '大錘'
qs.Filter("Username__exact", "大錘") // 相當於條件 name = '大錘'
qs.Filter("Username__iexact", "大錘") // 相當於條件 name LIKE '大錘'
qs.Filter("Username__iexact", "大錘") // 相當於條件 name LIKE '大錘'
qs.Filter("Username__contains", "大錘") // 相當於條件 name LIKE BINARY '%大錘%'   , BINARY 區分大小寫
qs.Filter("Username__icontains", "大錘") // 相當於條件 name LIKE '%大錘%'
qs.Filter("Username__istartswith", "大錘") // 相當於條件 name LIKE '大錘%'
qs.Filter("Username__iendswith", "大錘") // 相當於條件 name LIKE '%大錘'
qs.Filter("Username__isnull", true) // 相當於條件 name is null
qs.Filter("Username__isnull", false) // 相當於條件 name is not null

多個Filter函式呼叫使用 and 連線查詢條件。
例子:

qs.Filter("id__gt", 1).Filter("id__lt", 100) // 相當於條件 id > 1 and id < 100

三、處理複雜的查詢條件

上面的例子多個Filter函式呼叫只能生成and連線的查詢條件,那麼如果要設定or條件就不行了;beego orm為我們提供了Condition物件,用於生成查詢條件。

例子:

//  建立一個Condition物件
cond := orm.NewCondition()

// 組織查詢條件, 並返回一個新的Condition物件
cond1 := cond.And("Id__gt", 100).Or("City","shenzhen")
// 相當於條件 id > 100 or city = 'shenzhen'

var users []User

qs.SetCond(cond1). // 設定查詢條件
  Limit(10). // 限制返回資料函式
  All(&users) // 查詢多行資料

四、查詢資料

4.1 查詢多行資料

使用All函式可以返回多行資料。
例子:

// 建立orm物件
o := orm.NewOrm()

// 獲取 QuerySeter 物件,並設定表名orders
qs := o.QueryTable("users")

// 定義儲存查詢結果的變數
var users []User

// 使用QuerySeter 物件構造查詢條件,並執行查詢。
// 等價sql: select * from users where id > 1 and id < 100 limit 10
num, err := qs.Filter("Id__gt", 1).
		Filter("Id__lt", 100).
		Limit(10). // 限制返回行數
		All(&users) // 返回多行資料, 也可以設定返回指定欄位All(&users, "id", "username")

4.2 查詢一行資料

使用One函式返回一條記錄

var user User

// 等價sql: select * from users where id = 1 limit 1
err := o.QueryTable("users").Filter("id", 1).One(&user)

if err == orm.ErrNoRows {
    fmt.Printf("查詢不到資料")
}

One也可以返回指定欄位值, 例: One(&user, "id", "username")

4.3 Group By & Order BY

這裡介紹一個包含group by, order by語句的例子

// 建立orm物件
o := orm.NewOrm()

// 獲取 QuerySeter 物件,並設定表名orders
qs := o.QueryTable("users")

// 定義儲存查詢結果的變數
var users []User

// 使用QuerySeter 物件構造查詢條件,並執行查詢。
// 等價sql: select * from users where id > 1 and id < 100 group by city order by init_time desc limit 10
num, err := qs.Filter("Id__gt", 1).
		Filter("Id__lt", 100).
		GroupBy("City").   // 根據city欄位分組
		OrderBy("-InitTime").   // order by欄位名前面的減號 - , 代表倒序。
		Limit(10). // 限制返回行數
		All(&users)

if err != nil {
	panic(err)
}
fmt.Println("結果行數:", num)

4.4 Count統計總數

sql語句中的count語句的例子

// 這裡可以忽略錯誤。
num, _ := o.QueryTable("users").Filter("Id__gt", 1).Filter("Id__lt", 100).Count()

// 等價sql: select count(*) from users where id > 1 and id < 100

fmt.Printf("總數: %s", num)

五、更新資料

使用QuerySeter更新資料,可以根據複雜的查詢條件更新資料, 用法組織好查詢條件後呼叫Update函式即可。
例子:

// Update引數,使用的是orm.Params物件,這是一個map[string]interface{}型別, 用於指定我們要更新的資料
num, err := o.QueryTable("users").Filter("Id__gt", 1).Filter("Id__lt", 100).Update(orm.Params{
    "City": "深圳",
    "Password": "123456",
})

// 等價sql: update users set city = '深圳', password = '123456' where id > 1 and id < 100

fmt.Printf("影響行數: %s, %s", num, err)

六、刪除資料

組織好查詢條件後,呼叫Delete函式即可。

num, err := o.QueryTable("users").Filter("Id__gt", 1).Filter("Id__lt", 100).Delete()
// 等價sql: delete from users where id > 1 and id < 100
fmt.Printf("影響行數: %s, %s", num, err)