If you are looking for a small database for your fun project, I have something you might like. It is small, works as a key-value store and it's pure go.
What is Bolt?
Bolt is a pure Go key/value store inspired by Howard Chu's LMDB project. The goal of the project is to provide a simple, fast, and reliable database for projects that don't require a full database server such as Postgres or MySQL.
Since Bolt is meant to be used as such a low-level piece of functionality, simplicity is key. The API will be small and only focus on getting values and setting values. That's it.
How to use Bolt?
Installing
Bolt doesn't need any install other than go get
. It just works as a library. So your only need is adding it to go.mod
file.
go get github.com/boltdb/bolt
Creating database
After you can create your database like this.
db, err := bolt.Open("my.db", 0600, &bolt.Options{})
if err != nil {
log.Fatal(err)
}
defer db.Close()
In here you can add timeout to your database. Or you can set readonly if you don't need writing into. Just set them in &bolt.Options{}
.
Writing into database
You need to create bucket first. After than you can write your key/value data into bucket. Also tx.CreateBucketIfNotExists([]byte)
function is life saver.
db.Update(func(tx *bolt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists([]byte("todo"))
if err != nil {
return fmt.Errorf("create bucket: %s", err)
}
return bucket.Put([]byte("task-1"), []byte("Test BoltDB"))
})
If you have a bucket already you can write into it like this. Caution checking bucket is nil is important. Because if you try to use Put
on nil bucket your program will panic.
db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket([]byte("todo"))
if bucket == nil {
return fmt.Errorf("get bucket: FAILED")
}
return bucket.Put([]byte("task-1"), []byte("Test BoltDB additions"))
})
Querying data from database
Querying is as simple as writing. Just call your bucket and ask it for your data.
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("todo"))
if b == nil {
return fmt.Errorf("get bucket: FAILED")
}
fmt.Println(b.Get([]byte("task-1")))
// should return nil to complete the transaction
return nil
})
And here is simple way to iterate on all keys in one bucket.
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("todo"))
if b == nil {
return fmt.Errorf("get bucket: FAILED")
}
// we need cursor for iteration
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
fmt.Println("Key: ", string(k), " Value: ", string(v))
}
// should return nil to complete the transaction
return nil
})
Conclusion
- Bolt is a pure Go key/value store
- Bolt is native go library
- Bolt is supported everywhere which go is supported
- Creating, Writing and Querying inside Bolt is really easy.
Simple and powerful toolkit for BoltDB
Storm is a simple and powerful toolkit for BoltDB. Basically, Storm provides indexes, a wide range of methods to store and fetch data, an advanced query system, and much more.
GitHub: https://github.com/asdine/storm
Top comments (2)
I personally like: /github.com/xujiajun/nutsdb
(faster than BoltDB)
excellent article, I am implementing the Storm toolkit but, I have doubts about in which cases I should use buckets, what are they for, I think the documentation falls short and the other thing is that I am saving a struct that contains another struct, but I can not find data in the internal struct which I have as inline. Has anyone worked with this lib and knows how to make that query?