asdine/storm學(xué)習(xí)筆記

前言: github地址 asdine/storm
asdine/storm 是golang 開發(fā)的一個 orm工具. 內(nèi)置嵌入式數(shù)據(jù)庫為 golang 的流行 K/V 數(shù)據(jù)庫 bbolt

創(chuàng)建數(shù)據(jù)結(jié)構(gòu)

type User struct {
  ID int //主鍵,默認(rèn) ID 值為主鍵, 申明其他類型為主鍵: `storm:"id"`
  Group string `storm:"index"` //索引
  Email string `storm:"unique"` // 不可重復(fù)
  Name string // 普通字段, 不會創(chuàng)建索引
  Age int 
}

打開數(shù)據(jù)庫


db, err := storm.Open("my.db")

defer db.Close()

CRUD 以及數(shù)據(jù)表操作

//---------------以下是 數(shù)據(jù)庫 操作----------------------
// Init 為給定結(jié)構(gòu)創(chuàng)建索引和存儲桶
Init(data interface{}) error
eg:  err := db.Init(new(User))

// ReIndex 重建存儲桶的所有索引. 優(yōu)化數(shù)據(jù)庫使用
ReIndex(data interface{}) error
eg:  db.ReIndex(new(User)

// 保存結(jié)構(gòu)體數(shù)據(jù)
Save(data interface{}) error
eg: err := db.Save(&SimpleUser{ID: 10, Name: "John"})

// 更新結(jié)構(gòu)體數(shù)據(jù), 可以同時修改多個數(shù)據(jù)
Update(data interface{}) error
eg: err = db.Update(&User{ID: 10, Name: "Jack"})

// 更新單個字段
UpdateField(data interface{}, fieldName string, value interface{}) error
eg: err = db.UpdateField(&User{ID: 11}, "Name", "Jack")
附0值 eg:  err = db.UpdateField(&User{ID: 10}, "Age", int(0))

// 刪除整個表
Drop(data interface{}) error
eg: err = db.From("b1").Drop("b2")

// DeleteStruct 從關(guān)聯(lián)的存儲表中刪除結(jié)構(gòu)
DeleteStruct(data interface{}) error
eg: 
    u1 := IndexedNameUser{ID: 10, Name: "John", age: 10}
    err = db.DeleteStruct(&u1)

普通查詢
提供的方法

One(fieldName string, value interface{}, to interface{}) error

Find(fieldName string, value interface{}, to interface{}, options ...func(q *index.Options)) error

// AllByIndex 獲取在指定索引中索引的存儲桶的所有記錄
AllByIndex(fieldName string, to interface{}, options ...func(*index.Options)) error

// 如果沒有記錄,它不會返回任何錯誤宝恶,并且"to"參數(shù)設(shè)置為空切片
All(to interface{}, options ...func(*index.Options)) error

// 返回一個 query 對象, 使用 tree.go 提供的方法.
Select(matchers ...q.Matcher) Query

// 按指定范圍內(nèi)的指定索引返回一個或多個記錄
Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error

// 返回一個或多個記錄符隙,其給定字段以指定的前綴開頭
Prefix(fieldName string, prefix string, to interface{}, options ...func(*index.Options)) error

// 計數(shù)存儲桶的所有記錄
Count(data interface{}) (int, error)

type User struct{
    Name string `json:"name"`
    Age int `json:"age"`
}

案例

  • One
//定義接收參數(shù)
var user User

// 如果查詢到符合 Name = John 的數(shù)據(jù), 賦值給 user 變量
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
err = db.One("Name", "John", &user)
  • Find
//定義接收參數(shù)數(shù)組
var users []User

// 如果查詢到符合 Name = John 的數(shù)據(jù), 賦值給 users 變量
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
//可以添加 option 參數(shù)
err = db.Find("Name", "John", &users)
err = db.One("Name", "John", &user,  storm.Limit(10), storm.Skip(10), storm.Reverse())
  • AllByIndex
//定義接收參數(shù)數(shù)組
var users []User

// 根據(jù)索引,查詢?nèi)康臄?shù)據(jù), 
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
err = db.AllByIndex("Name", &users)
  • All
//定義接收參數(shù)數(shù)組
var users []User

// 查詢?nèi)康臄?shù)據(jù)
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
//如果沒有記錄,它將不返回任何錯誤垫毙,并且"to"參數(shù)設(shè)置為空切片霹疫。
err = db.All(&users)
  • Select 高級查詢用法
//定義接收參數(shù)數(shù)組
var users []User

//根據(jù)Matcher構(gòu)造Query 對象
query := db.Select(q.Gte("ID", 10), q.Lte("ID", 100))

query.Find(&users) //其他方法參考 query.go
  • Range 范圍查詢
//定義接收參數(shù)數(shù)組
var users []User

//設(shè)定一個范圍, 查詢
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
err := db.Range("Age", 10, 21, &users)
  • Prefix 模糊查詢
//定義接收參數(shù)數(shù)組
var users []User

//設(shè)定字符前綴, 查詢滿足前綴給定值的數(shù)據(jù)
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
err := db.Prefix("Name", "Jo", &users)
  • Count 查詢數(shù)據(jù)量
//查詢bucket 中的數(shù)據(jù)總量
//如果數(shù)據(jù)量為0, 不會返回 err.
count, err := db.Prefix(&User{})

高級查詢 匹配器 Matcher 接口

// Eq 匹配器,檢查給定字段名(field) 是否等于給定值(value) 综芥。
func Eq(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &cmp{value: v, token: token.EQL})
}
eg: q.Eq("Name","Jone")

// EqF 匹配器, 檢查給定字段名 field1是否等于給定的另一個字段名稱field2
func EqF(field1, field2 string) Matcher {
   return NewField2FieldMatcher(field1, field2, token.EQL)
}

// StrictEq 匹配器, 檢查給定字段名field是否深度等于(deeply equal) 給定的值
func StrictEq(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &strictEq{value: v})
}

// Gt 匹配器, 檢查給定字段名field是否大于給定的值
func Gt(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &cmp{value: v, token: token.GTR})
}

// GtF 匹配器, 檢查給定字段名 field1是否大于給定的另一個字段名稱field2
func GtF(field1, field2 string) Matcher {
   return NewField2FieldMatcher(field1, field2, token.GTR)
}

// Gte 匹配器, 檢查給定字段名field是否大于等于 >= 給定的值
func Gte(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &cmp{value: v, token: token.GEQ})
}

// GteF 匹配器, 檢查給定字段名 field1是否大于或等于給定的另一個字段名稱field2
func GteF(field1, field2 string) Matcher {
   return NewField2FieldMatcher(field1, field2, token.GEQ)
}

// Lt 匹配器, 檢查給定字段名field是否小于給定的值
func Lt(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &cmp{value: v, token: token.LSS})
}

// LtF 匹配器, 檢查給定字段名 field1是否小于給定的另一個字段名稱field2
func LtF(field1, field2 string) Matcher {
   return NewField2FieldMatcher(field1, field2, token.LSS)
}

// Lte 匹配器, 檢查給定字段名field是否小于等于給定的值
func Lte(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &cmp{value: v, token: token.LEQ})
}

// LteF 匹配器, 檢查給定字段名 field1是否小于等于給定的另一個字段名稱field2
func LteF(field1, field2 string) Matcher {
   return NewField2FieldMatcher(field1, field2, token.LEQ)
}

// In 匹配器, 檢查給定字段名field是否等于給定的切片中的一個值
// v 必須是一個切片.
func In(field string, v interface{}) Matcher {
   return NewFieldMatcher(field, &in{list: v})
}
eg: q.Eq("Name",["a","b","c"])

// True 匹配器, 總是返回 true
func True() Matcher { return &trueMatcher{} }

// Or 匹配器,  傳入多個 Matcher 對象,  或的關(guān)系
func Or(matchers ...Matcher) Matcher { return &or{children: matchers} }
eg: q.Or( q.Eq("Name":"Jone" ), q.Eq("Name":"Zach"))

// And 匹配器,  傳入多個 Matcher 對象, 全部滿足, 與的關(guān)系
func And(matchers ...Matcher) Matcher { return &and{children: matchers} }


// Not 匹配器,  傳入多個 Matcher 對象, 全部不滿足, 非的關(guān)系
func Not(matchers ...Matcher) Matcher { return &not{children: matchers} }

// Re 匹配器,  重新創(chuàng)建一個正則匹配規(guī)則, 檢查給定的字段 field 是否匹配給定的正在規(guī)則
// 請注意丽蝎,這僅支持類型字符串或 [字節(jié)]的字段。
// 第二個參數(shù)寫入正則的字符串表達(dá)式
func Re(field string, re string) Matcher { *** }
eg:  q.Re("A", "\\d+")   

高級查詢 匹配器 Query 接口
提供的方法

// 按給定編號跳過匹配記錄
Skip(int) Query

// 返回指定數(shù)量的數(shù)據(jù)
Limit(int) Query

// 按給定字段從左到右的降序排列膀藐。
OrderBy(...string) Query
eg: q.OrderBy("Name", "Age")

// 切換排序方案: 降序 <--> 升序
Reverse() Query

// 表名稱
Bucket(string) Query

// 查詢匹配列表
Find(interface{}) error

// 得第一條匹配記錄
First(interface{}) error

// 刪除所有匹配的記錄
Delete(interface{}) error

// 所有匹配記錄的數(shù)量
Count(interface{}) (int, error)

// 返回所有記錄的原始數(shù)據(jù). 未進(jìn)行解碼操作
Raw() ([][]byte, error)

// 對每個原始元素執(zhí)行給定的功能
RawEach(func([]byte, []byte) error) error

// 對每個元素執(zhí)行給定的功能
Each(interface{}, func(interface{}) error) error

KV數(shù)據(jù)庫操作
直接通過數(shù)據(jù) Key 操作數(shù)據(jù)庫, 提供的方法有:

// 獲取第 N 個元素
// 如果查詢不到數(shù)據(jù), 返回 err = storm.ErrNotFound
Get(bucketName string, key interface{}, to interface{}) error
eg:  查詢第10條元素
    u2 := IndexedNameUser{}
    err = db.Get("IndexedNameUser", 10, &u2)

// 添加 KV 數(shù)據(jù)庫的值
Set(bucketName string, key interface{}, value interface{}) error
eg:  err := db.Set("files", "myfile.csv", "a,b,c,d")

// 刪除KV 數(shù)據(jù)庫的值
Delete(bucketName string, key interface{}) error
eg:  err = db.Delete("files", "myfile.csv")

// 獲取 key 值為 bytes 類型的 value 值
GetBytes(bucketName string, key interface{}) ([]byte, error)

// 設(shè)置 key 值為 bytes 類型的 value 值
SetBytes(bucketName string, key interface{}, value []byte) error

// KeyExists 判斷 key 值是否已經(jīng)被創(chuàng)建
KeyExists(bucketName string, key interface{}) (bool, error)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載屠阻,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者红省。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市国觉,隨后出現(xiàn)的幾起案子吧恃,更是在濱河造成了極大的恐慌,老刑警劉巖麻诀,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痕寓,死亡現(xiàn)場離奇詭異,居然都是意外死亡针饥,警方通過查閱死者的電腦和手機厂抽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丁眼,“玉大人筷凤,你說我怎么就攤上這事“撸” “怎么了藐守?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹂风。 經(jīng)常有香客問我卢厂,道長,這世上最難降的妖魔是什么惠啄? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任慎恒,我火速辦了婚禮,結(jié)果婚禮上撵渡,老公的妹妹穿的比我還像新娘融柬。我一直安慰自己,他們只是感情好趋距,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布粒氧。 她就那樣靜靜地躺著,像睡著了一般节腐。 火紅的嫁衣襯著肌膚如雪外盯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天翼雀,我揣著相機與錄音饱苟,去河邊找鬼。 笑死锅纺,一個胖子當(dāng)著我的面吹牛掷空,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坦弟,長吁一口氣:“原來是場噩夢啊……” “哼护锤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起酿傍,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤烙懦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赤炒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氯析,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年莺褒,在試婚紗的時候發(fā)現(xiàn)自己被綠了掩缓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遵岩,死狀恐怖你辣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尘执,我是刑警寧澤舍哄,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站誊锭,受9級特大地震影響表悬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丧靡,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一蟆沫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧温治,春花似錦饥追、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽救崔。三九已至惶看,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間六孵,已是汗流浹背纬黎。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留劫窒,地道東北人本今。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冠息。 傳聞我的和親對象是個殘疾皇子挪凑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354