商业公链之区块链技术使用的常见库(四)------Go语言内存数据库 "github.com/tidwall/buntdb"

BuntDB是纯Go开发的、低层级的(low-level)的、可嵌入的key/value内存数据库(IMDB),数据持久化存储,遵从ACID,支持自定义索引和地理空间 数据。BuntDB旨在给用户提供可靠稳定高效的数据库。

特点:

1.因为是内存数据库,所以支持快速的读和写

2.可采用简单的API,实现数据库嵌入功能

3.20维以下的空间索引;对地理空间数据有用

4.支持创建任何数据类型的自定义索引,JSON文档中的索引字段,支持多值索引;类似于SQL多列索引

5.支持String, Uint, Int, Float等内置类型,数据的灵活迭代;升序、降序和范围

6.紧密的代码库,在1K LOC使用CLOC命令

7.具有数据库的可靠性恢复和回滚机制,支持 ACID

用法:

1.安装buntdb数据库:go get -u github.com/tidwall/buntdb

2.引入buntdb数据库:import "github.com/tidwall/buntdb"

3.依据数据库路径打开数据库,没有则创建一个数据库:db, _ := buntdb.Open("data.db")

 或者在内存建立一个临时数据库,不做持久化存储:db, _ := buntdb.Open(":memory:")

4.以只读模式读取数据库:

err := db.View(func(tx *buntdb.Tx) error {

...

return nil

})

以读写模式读取数据库:

err := db.Update(func(tx *buntdb.Tx) error {

...

return nil

})

5.以读写模式存储键值"mykey", "myvalue":

err := db.Update(func(tx *buntdb.Tx) error {

_, _, err := tx.Set("mykey", "myvalue", nil)

return err

})

以只读模式读取键"mykey"对应值,如果不存在键则返回错误ErrNotFound:

err := db.View(func(tx *buntdb.Tx) error {

val, err := tx.Get("mykey")

if err != nil{

return err

}

fmt.Printf("value is %s\n", val)

return nil

})

6.以只读模式迭代Ascend读取全部键值,同样还有AscendGreaterOrEqual, AscendLessThan, AscendRange, AscendEqual, Descend, DescendLessOrEqual, DescendGreaterThan, DescendRange, 和DescendEqual,具体用法查看文档:

err := db.View(func(tx *buntdb.Tx) error {

err := tx.Ascend("", func(key, value string) bool {

fmt.Printf("key: %s, value: %s\n", key, value)

})

return err

})

7.创建自定义索引,索引名name,*代表匹配任何格式,索引对应值排序为与大小写无关字母string排序:db.CreateIndex("names", "*", buntdb.IndexString)

插入索引和其对应的键值:

db.Update(func(tx *buntdb.Tx) error {

tx.Set("user:0:name", "tom", nil)

return nil

})

只读模式读取索引name对应的键值:

db.View(func(tx *buntdb.Tx) error {

tx.Ascend("names", func(key, val string) bool {

fmt.Printf(buf, "%s %s\n", key, val)

return true

})

return nil

})

只有具有前缀user:的键的项才会添加到名称索引中:db.CreateIndex("names", "user:*", buntdb.IndexString)

8.除了indexstring之外,还有indexint、indexuint和indexfloat。这些是用于索引的内置类型。因此,要创建一个以数字顺序排列在年龄键上的索引,我们可以使用:

db.CreateIndex("ages", "user:*:age", buntdb.IndexInt)

添加值:

db.Update(func(tx *buntdb.Tx) error {

tx.Set("user:0:age", "35", nil)

return nil

})

读取值,输出结果年龄数字从小到大排序:

db.View(func(tx *buntdb.Tx) error {

tx.Ascend("ages", func(key, val string) bool {

fmt.Printf(buf, "%s %s\n", key, val)

return true

})

return nil

})

9.创建空间位置索引,例如索引fleet对应结构"fleet:*:pos"经纬度矩形值:db.CreateSpatialIndex("fleet", "fleet:*:pos", buntdb.IndexRect),该IndexRect函数使用不同的格式进行渲染,例如众所周知的文本或geojson。

插入经纬度

db.Update(func(tx *buntdb.Tx) error {

tx.Set("fleet:0:pos", "[-115.567 33.532]", nil)

return nil

})

Intersects函数读取 "[-117 30],[-112 36]"对应矩形内的值:

db.View(func(tx *buntdb.Tx) error {

tx.Intersects("fleet", "[-117 30],[-112 36]", func(key, val string) bool {

...

return true

})

return nil

})

Nearby函数,由 "[-113 33]"近到远排序读取值:

db.View(func(tx *buntdb.Tx) error {

tx.Nearby("fleet", "[-113 33]", func(key, val string, dist float64) bool {

...

return true

})

return nil

})

10.创建json格式索引last_name,按照last进行排序:db.CreateIndex("last_name", "*", buntdb.IndexJSON("name.last"))

插入json格式键值:

db.Update(func(tx *buntdb.Tx) error {

tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)

return nil

})

读取last_name对应键值,以last属性进行升序排序:

db.View(func(tx *buntdb.Tx) error {

fmt.Println("Order by last name")

tx.Ascend("last_name", func(key, value string) bool {

fmt.Printf("%s: %s\n", key, value)

return true

})

return nil

})

11.使用buntdb,可以在一个索引上联接多个值。这类似于传统SQL数据库中的多列索引。

在本例中,我们在“name.last”和“age”上创建多值索引,即先进行last排序,若相同再进行age排序:db.CreateIndex("last_name_age", "*", buntdb.IndexJSON("name.last"), buntdb.IndexJSON("age"))

12.Buntdb当前不支持在迭代过程中删除密钥。作为解决方法,您需要在迭代器完成后删除键:

var delkeys []string

tx.AscendKeys("object:*", func(k, v string) bool {

if someCondition(k) == true {

delkeys = append(delkeys, k)

}

return true // continue

})

for _, k := range delkeys {

if _, err = tx.Delete(k); err != nil {

return err

}

}

13.关闭数据库:defer db.Close()

示例源码:阅读原文,用法文档:https://godoc.org/github.com/tidwall/buntdb#ex-package--DescKeys

希望大家关注我的微信公众号,日更一篇区块链技术博客不易,有疑问可以后台留言。

猜你喜欢

转载自blog.csdn.net/Rcvisual/article/details/88941546