A simple demo of boltdb.
Compare prefix and range scans with the levelup approach described in the Rod Vagg's article, LevelDB and Node: Getting Up and Running.
See also the intro articles/talks by ...
A simple demo of boltdb.
Compare prefix and range scans with the levelup approach described in the Rod Vagg's article, LevelDB and Node: Getting Up and Running.
See also the intro articles/talks by ...
package demo | |
import ( | |
"fmt" | |
"log" | |
"time" | |
"path" | |
"bytes" | |
"runtime" | |
"encoding/json" | |
"encoding/gob" | |
"github.com/boltdb/bolt" | |
) | |
var db *bolt.DB | |
var open bool | |
func Open() error { | |
var err error | |
_, filename, _, _ := runtime.Caller(0) // get full path of this file | |
dbfile := path.Join(path.Dir(filename), "data.db") | |
config := &bolt.Options{Timeout: 1 * time.Second} | |
db, err = bolt.Open(dbfile, 0600, config) | |
if err != nil { | |
log.Fatal(err) | |
} | |
open = true | |
return nil | |
} | |
func Close() { | |
open = false | |
db.Close() | |
} | |
type Person struct { | |
ID string | |
Name string | |
Age string | |
Job string | |
} | |
func (p *Person) save() error { | |
if !open { | |
return fmt.Errorf("db must be opened before saving!") | |
} | |
err := db.Update(func(tx *bolt.Tx) error { | |
people, err := tx.CreateBucketIfNotExists([]byte("people")) | |
if err != nil { | |
return fmt.Errorf("create bucket: %s", err) | |
} | |
enc, err := p.encode() | |
if err != nil { | |
return fmt.Errorf("could not encode Person %s: %s", p.ID, err) | |
} | |
err = people.Put([]byte(p.ID), enc) | |
return err | |
}) | |
return err | |
} | |
func (p *Person) gobEncode() ([]byte, error) { | |
buf := new(bytes.Buffer) | |
enc := gob.NewEncoder(buf) | |
err := enc.Encode(p) | |
if err != nil { | |
return nil, err | |
} | |
return buf.Bytes(), nil | |
} | |
func gobDecode(data []byte) (*Person, error) { | |
var p *Person | |
buf := bytes.NewBuffer(data) | |
dec := gob.NewDecoder(buf) | |
err := dec.Decode(&p) | |
if err != nil { | |
return nil, err | |
} | |
return p, nil | |
} | |
func (p *Person) encode() ([]byte, error) { | |
enc, err := json.Marshal(p) | |
if err != nil { | |
return nil, err | |
} | |
return enc, nil | |
} | |
func decode(data []byte) (*Person, error) { | |
var p *Person | |
err := json.Unmarshal(data, &p) | |
if err != nil { | |
return nil, err | |
} | |
return p, nil | |
} | |
func GetPerson(id string) (*Person, error) { | |
if !open { | |
return nil, fmt.Errorf("db must be opened before saving!") | |
} | |
var p *Person | |
err := db.View(func(tx *bolt.Tx) error { | |
var err error | |
b := tx.Bucket([]byte("people")) | |
k := []byte(id) | |
p, err = decode(b.Get(k)) | |
if err != nil { | |
return err | |
} | |
return nil | |
}) | |
if err != nil { | |
fmt.Printf("Could not get Person ID %s", id) | |
return nil, err | |
} | |
return p, nil | |
} | |
func List(bucket string) { | |
db.View(func(tx *bolt.Tx) error { | |
c := tx.Bucket([]byte(bucket)).Cursor() | |
for k, v := c.First(); k != nil; k, v = c.Next() { | |
fmt.Printf("key=%s, value=%s\n", k, v) | |
} | |
return nil | |
}) | |
} | |
func ListPrefix(bucket, prefix string) { | |
db.View(func(tx *bolt.Tx) error { | |
c := tx.Bucket([]byte(bucket)).Cursor() | |
p := []byte(prefix) | |
for k, v := c.Seek(p); bytes.HasPrefix(k, p); k, v = c.Next() { | |
fmt.Printf("key=%s, value=%s\n", k, v) | |
} | |
return nil | |
}) | |
} | |
func ListRange(bucket, start, stop string) { | |
db.View(func(tx *bolt.Tx) error { | |
c := tx.Bucket([]byte(bucket)).Cursor() | |
min := []byte(start) | |
max := []byte(stop) | |
for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; | |
k, v = c.Next() { | |
fmt.Printf("%s: %s\n", k, v) | |
} | |
return nil | |
}) | |
} |
package main | |
import ( | |
"github.com/joyrexus/bolt/demo" | |
) | |
func main() { | |
demo.Open() | |
defer demo.Close() | |
/* | |
// A Person struct consists of ID, Name, Age, Job. | |
peeps := []*Person{ | |
{"100", "Bill Joy", "60", "Programmer"}, | |
{"101", "Peter Norvig", "58", "Programmer"}, | |
{"102", "Donald Knuth", "77", "Programmer"}, | |
{"103", "Jeff Dean", "47", "Programmer"}, | |
{"104", "Rob Pike", "59", "Programmer"}, | |
{"200", "Brian Kernighan", "73", "Programmer"}, | |
{"201", "Ken Thompson", "72", "Programmer"}, | |
} | |
// Persist people in the database. | |
for _, p := range peeps { | |
p.save() | |
} | |
// Get a person from the database by their ID. | |
for _, id := range []string{"100", "101"} { | |
p, err := GetPerson(id) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Println(p) | |
} | |
*/ | |
demo.List("people") // each key/val in people bucket | |
demo.ListPrefix("people", "20") // ... with key prefix `20` | |
demo.ListRange("people", "101", "103") // ... within range `101` to `103` | |
} |
Hi.
What if I want to search for a persons name, age, or job?