asdine/storm学习笔记

前言: github地址 asdine/storm
asdine/storm 是golang 开发的一个 orm工具. 内置嵌入式数据库为 golang 的流行 K/V 数据库 bbolt

创建数据结构

type User struct {
  ID int //主键,默认 ID 值为主键, 申明其他类型为主键: `storm:"id"`
  Group string `storm:"index"` //索引
  Email string `storm:"unique"` // 不可重复
  Name string // 普通字段, 不会创建索引
  Age int 
}

打开数据库


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

defer db.Close()

CRUD 以及数据表操作

//---------------以下是 数据库 操作----------------------
// Init 为给定结构创建索引和存储桶
Init(data interface{}) error
eg:  err := db.Init(new(User))

// ReIndex 重建存储桶的所有索引. 优化数据库使用
ReIndex(data interface{}) error
eg:  db.ReIndex(new(User)

// 保存结构体数据
Save(data interface{}) error
eg: err := db.Save(&SimpleUser{ID: 10, Name: "John"})

// 更新结构体数据, 可以同时修改多个数据
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 从关联的存储表中删除结构
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"参数设置为空切片
All(to interface{}, options ...func(*index.Options)) error

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

// 按指定范围内的指定索引返回一个或多个记录
Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error

// 返回一个或多个记录,其给定字段以指定的前缀开头
Prefix(fieldName string, prefix string, to interface{}, options ...func(*index.Options)) error

// 计数存储桶的所有记录
Count(data interface{}) (int, error)

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

案例

  • One
//定义接收参数
var user User

// 如果查询到符合 Name = John 的数据, 赋值给 user 变量
// 如果查询不到数据, 返回 err = storm.ErrNotFound
err = db.One("Name", "John", &user)
  • Find
//定义接收参数数组
var users []User

// 如果查询到符合 Name = John 的数据, 赋值给 users 变量
// 如果查询不到数据, 返回 err = storm.ErrNotFound
//可以添加 option 参数
err = db.Find("Name", "John", &users)
err = db.One("Name", "John", &user,  storm.Limit(10), storm.Skip(10), storm.Reverse())
  • AllByIndex
//定义接收参数数组
var users []User

// 根据索引,查询全部的数据, 
// 如果查询不到数据, 返回 err = storm.ErrNotFound
err = db.AllByIndex("Name", &users)
  • All
//定义接收参数数组
var users []User

// 查询全部的数据
// 如果查询不到数据, 返回 err = storm.ErrNotFound
//如果没有记录,它将不返回任何错误,并且"to"参数设置为空切片。
err = db.All(&users)
  • Select 高级查询用法
//定义接收参数数组
var users []User

//根据Matcher构造Query 对象
query := db.Select(q.Gte("ID", 10), q.Lte("ID", 100))

query.Find(&users) //其他方法参考 query.go
  • Range 范围查询
//定义接收参数数组
var users []User

//设定一个范围, 查询
// 如果查询不到数据, 返回 err = storm.ErrNotFound
err := db.Range("Age", 10, 21, &users)
  • Prefix 模糊查询
//定义接收参数数组
var users []User

//设定字符前缀, 查询满足前缀给定值的数据
// 如果查询不到数据, 返回 err = storm.ErrNotFound
err := db.Prefix("Name", "Jo", &users)
  • Count 查询数据量
//查询bucket 中的数据总量
//如果数据量为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 对象,  或的关系
func Or(matchers ...Matcher) Matcher { return &or{children: matchers} }
eg: q.Or( q.Eq("Name":"Jone" ), q.Eq("Name":"Zach"))

// And 匹配器,  传入多个 Matcher 对象, 全部满足, 与的关系
func And(matchers ...Matcher) Matcher { return &and{children: matchers} }


// Not 匹配器,  传入多个 Matcher 对象, 全部不满足, 非的关系
func Not(matchers ...Matcher) Matcher { return &not{children: matchers} }

// Re 匹配器,  重新创建一个正则匹配规则, 检查给定的字段 field 是否匹配给定的正在规则
// 请注意,这仅支持类型字符串或 [字节]的字段。
// 第二个参数写入正则的字符串表达式
func Re(field string, re string) Matcher { *** }
eg:  q.Re("A", "\\d+")   

高级查询 匹配器 Query 接口
提供的方法

// 按给定编号跳过匹配记录
Skip(int) Query

// 返回指定数量的数据
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

// 所有匹配记录的数量
Count(interface{}) (int, error)

// 返回所有记录的原始数据. 未进行解码操作
Raw() ([][]byte, error)

// 对每个原始元素执行给定的功能
RawEach(func([]byte, []byte) error) error

// 对每个元素执行给定的功能
Each(interface{}, func(interface{}) error) error

KV数据库操作
直接通过数据 Key 操作数据库, 提供的方法有:

// 获取第 N 个元素
// 如果查询不到数据, 返回 err = storm.ErrNotFound
Get(bucketName string, key interface{}, to interface{}) error
eg:  查询第10条元素
    u2 := IndexedNameUser{}
    err = db.Get("IndexedNameUser", 10, &u2)

// 添加 KV 数据库的值
Set(bucketName string, key interface{}, value interface{}) error
eg:  err := db.Set("files", "myfile.csv", "a,b,c,d")

// 删除KV 数据库的值
Delete(bucketName string, key interface{}) error
eg:  err = db.Delete("files", "myfile.csv")

// 获取 key 值为 bytes 类型的 value 值
GetBytes(bucketName string, key interface{}) ([]byte, error)

// 设置 key 值为 bytes 类型的 value 值
SetBytes(bucketName string, key interface{}, value []byte) error

// KeyExists 判断 key 值是否已经被创建
KeyExists(bucketName string, key interface{}) (bool, error)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342