Documentation
¶
Index ¶
- Constants
- Variables
- func AutoIncrement() func(*DB) error
- func Batch() func(*DB) error
- func BoltOptions(mode os.FileMode, options *bolt.Options) func(*DB) error
- func Codec(c codec.MarshalUnmarshaler) func(*DB) error
- func Limit(limit int) func(*index.Options)
- func Reverse() func(*index.Options)
- func Root(root ...string) func(*DB) error
- func Skip(offset int) func(*index.Options)
- func UseDB(b *bolt.DB) func(*DB) error
- type BucketScanner
- type DB
- func (s *DB) All(to interface{}, options ...func(*index.Options)) error
- func (s *DB) AllByIndex(fieldName string, to interface{}, options ...func(*index.Options)) error
- func (s *DB) Begin(writable bool) (Node, error)
- func (s *DB) Bucket() []string
- func (s *DB) Close() error
- func (s *DB) Codec() codec.MarshalUnmarshaler
- func (s *DB) Commit() error
- func (s *DB) Count(data interface{}) (int, error)
- func (s *DB) CreateBucketIfNotExists(tx *bolt.Tx, bucket string) (*bolt.Bucket, error)
- func (s *DB) Delete(bucketName string, key interface{}) error
- func (s *DB) DeleteStruct(data interface{}) error
- func (s *DB) Drop(data interface{}) error
- func (s *DB) Find(fieldName string, value interface{}, to interface{}, ...) error
- func (s *DB) From(root ...string) Node
- func (s *DB) Get(bucketName string, key interface{}, to interface{}) error
- func (s *DB) GetBucket(tx *bolt.Tx, children ...string) *bolt.Bucket
- func (s *DB) GetBytes(bucketName string, key interface{}) ([]byte, error)
- func (s *DB) Init(data interface{}) error
- func (s *DB) One(fieldName string, value interface{}, to interface{}) error
- func (s *DB) PrefixScan(prefix string) []Node
- func (s *DB) Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error
- func (s *DB) RangeScan(min, max string) []Node
- func (s *DB) ReIndex(data interface{}) error
- func (s *DB) Remove(data interface{}) error
- func (s *DB) Rollback() error
- func (s *DB) Save(data interface{}) error
- func (s *DB) Select(matchers ...q.Matcher) Query
- func (s *DB) Set(bucketName string, key interface{}, value interface{}) error
- func (s *DB) SetBytes(bucketName string, key interface{}, value []byte) error
- func (s *DB) Update(data interface{}) error
- func (s *DB) UpdateField(data interface{}, fieldName string, value interface{}) error
- func (s *DB) WithBatch(enabled bool) Node
- func (s *DB) WithCodec(codec codec.MarshalUnmarshaler) Node
- func (s *DB) WithTransaction(tx *bolt.Tx) Node
- type Finder
- type KeyValueStore
- type Node
- type Query
- type Tx
- type TypeStore
Examples ¶
Constants ¶
const Version = "1.0.0"
Version of Storm
Variables ¶
var ( // ErrNoID is returned when no ID field or id tag is found in the struct. ErrNoID = errors.New("missing struct tag id or ID field") // ErrZeroID is returned when the ID field is a zero value. ErrZeroID = errors.New("id field must not be a zero value") // ErrBadType is returned when a method receives an unexpected value type. ErrBadType = errors.New("provided data must be a struct or a pointer to struct") // ErrAlreadyExists is returned uses when trying to set an existing value on a field that has a unique index. ErrAlreadyExists = errors.New("already exists") // ErrNilParam is returned when the specified param is expected to be not nil. ErrNilParam = errors.New("param must not be nil") // ErrUnknownTag is returned when an unexpected tag is specified. ErrUnknownTag = errors.New("unknown tag") // ErrIdxNotFound is returned when the specified index is not found. ErrIdxNotFound = errors.New("index not found") // ErrSlicePtrNeeded is returned when an unexpected value is given, instead of a pointer to slice. ErrSlicePtrNeeded = errors.New("provided target must be a pointer to slice") // ErrSlicePtrNeeded is returned when an unexpected value is given, instead of a pointer to struct. ErrStructPtrNeeded = errors.New("provided target must be a pointer to struct") // ErrSlicePtrNeeded is returned when an unexpected value is given, instead of a pointer. ErrPtrNeeded = errors.New("provided target must be a pointer to a valid variable") // ErrNoName is returned when the specified struct has no name. ErrNoName = errors.New("provided target must have a name") // ErrNotFound is returned when the specified record is not saved in the bucket. ErrNotFound = errors.New("not found") // ErrNotInTransaction is returned when trying to rollback or commit when not in transaction. ErrNotInTransaction = errors.New("not in transaction") // ErrUnAddressable is returned when a struct or an exported field of a struct is unaddressable ErrUnAddressable = errors.New("unaddressable value") // ErrIncompatibleValue is returned when trying to set a value with a different type than the chosen field ErrIncompatibleValue = errors.New("incompatible value") // ErrDifferentCodec is returned when using a codec different than the first codec used with the bucket. ErrDifferentCodec = errors.New("the selected codec is incompatible with this bucket") )
Errors
Functions ¶
func AutoIncrement ¶
AutoIncrement used to enable bolt.NextSequence on empty integer ids. Deprecated: Set the increment tag to the id field instead.
func Batch ¶ added in v0.5.0
Batch enables the use of batch instead of update for read-write transactions.
func BoltOptions ¶
BoltOptions used to pass options to BoltDB.
func Codec ¶
func Codec(c codec.MarshalUnmarshaler) func(*DB) error
Codec used to set a custom encoder and decoder. The default is JSON.
func Limit ¶
Limit sets the maximum number of records to return
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.All(&users, storm.Limit(2))
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 2
func Skip ¶
Skip sets the number of records to skip
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.All(&users, storm.Skip(1))
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 2
func UseDB ¶
UseDB allow Storm to use an existing open Bolt.DB. Warning: storm.DB.Close() will close the bolt.DB instance.
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
"github.com/asdine/storm"
"github.com/boltdb/bolt"
)
func main() {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
defer os.RemoveAll(dir)
bDB, err := bolt.Open(filepath.Join(dir, "bolt.db"), 0600, &bolt.Options{Timeout: 10 * time.Second})
if err != nil {
log.Fatal(err)
}
db, _ := storm.Open("", storm.UseDB(bDB))
defer db.Close()
err = db.Save(&User{ID: 10})
if err != nil {
log.Fatal(err)
}
var user User
err = db.One("ID", 10, &user)
fmt.Println(err)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
Output: <nil>
Types ¶
type BucketScanner ¶
type BucketScanner interface {
// PrefixScan scans the root buckets for keys matching the given prefix.
PrefixScan(prefix string) []Node
// PrefixScan scans the buckets in this node for keys matching the given prefix.
RangeScan(min, max string) []Node
}
A BucketScanner scans a Node for a list of buckets
type DB ¶
type DB struct {
// Path of the database file
Path string
// Bolt is still easily accessible
Bolt *bolt.DB
// contains filtered or unexported fields
}
DB is the wrapper around BoltDB. It contains an instance of BoltDB and uses it to perform all the needed operations
func (*DB) All ¶
All get all the records of a bucket
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.All(&users)
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 3
func (*DB) AllByIndex ¶
AllByIndex gets all the records of a bucket that are indexed in the specified index
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.AllByIndex("CreatedAt", &users)
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 3
func (*DB) Begin ¶
Begin starts a new transaction.
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
// both start out with a balance of 10000 cents
var account1, account2 Account
tx, err := db.Begin(true)
if err != nil {
log.Fatal(err)
}
defer tx.Rollback()
err = tx.One("ID", 1, &account1)
if err != nil {
log.Fatal(err)
}
err = tx.One("ID", 2, &account2)
if err != nil {
log.Fatal(err)
}
account1.Amount -= 1000
account2.Amount += 1000
err = tx.Save(&account1)
if err != nil {
log.Fatal(err)
}
err = tx.Save(&account2)
if err != nil {
log.Fatal(err)
}
tx.Commit()
var account1Reloaded, account2Reloaded Account
err = db.One("ID", 1, &account1Reloaded)
if err != nil {
log.Fatal(err)
}
err = db.One("ID", 2, &account2Reloaded)
if err != nil {
log.Fatal(err)
}
fmt.Println("Amount in account 1:", account1Reloaded.Amount)
fmt.Println("Amount in account 2:", account2Reloaded.Amount)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Amount in account 1: 9000 Amount in account 2: 11000
func (*DB) Bucket ¶
Bucket returns the root bucket name as a slice. In the normal, simple case this will be empty.
func (*DB) Codec ¶
func (s *DB) Codec() codec.MarshalUnmarshaler
Codec returns the EncodeDecoder used by this instance of Storm
func (*DB) CreateBucketIfNotExists ¶
CreateBucketIfNotExists creates the bucket below the current node if it doesn't already exist.
func (*DB) DeleteStruct ¶
DeleteStruct deletes a structure from the associated bucket
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var user User
err := db.One("ID", 1, &user)
if err != nil {
log.Fatal(err)
}
err = db.DeleteStruct(&user)
fmt.Println(err)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: <nil>
func (*DB) Drop ¶
Drop a bucket
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var user User
err := db.One("Email", "john@provider.com", &user)
if err != nil {
log.Fatal(err)
}
err = db.Drop("User")
if err != nil {
log.Fatal(err)
}
// One only works for indexed fields.
err = db.One("Email", "john@provider.com", &user)
fmt.Println(err)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: not found
func (*DB) Find ¶
func (s *DB) Find(fieldName string, value interface{}, to interface{}, options ...func(q *index.Options)) error
Find returns one or more records by the specified index
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.Find("Group", "staff", &users)
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 3
func (*DB) From ¶
From returns a new Storm node with a new bucket root. All DB operations on the new node will be executed relative to the given bucket.
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
// Create some sub buckets to partition the data.
privateNotes := db.From("notes", "private")
workNotes := db.From("notes", "work")
err := privateNotes.Save(&Note{ID: "private1", Text: "This is some private text."})
if err != nil {
log.Fatal(err)
}
err = workNotes.Save(&Note{ID: "work1", Text: "Work related."})
if err != nil {
log.Fatal(err)
}
var privateNote, workNote, personalNote Note
err = privateNotes.One("ID", "work1", &workNote)
// Not found: Wrong bucket.
fmt.Println(err)
err = workNotes.One("ID", "work1", &workNote)
if err != nil {
log.Fatal(err)
}
err = privateNotes.One("ID", "private1", &privateNote)
if err != nil {
log.Fatal(err)
}
fmt.Println(workNote.Text)
fmt.Println(privateNote.Text)
// These can be nested further if needed:
personalNotes := privateNotes.From("personal")
err = personalNotes.Save(&Note{ID: "personal1", Text: "This is some very personal text."})
if err != nil {
log.Fatal(err)
}
err = personalNotes.One("ID", "personal1", &personalNote)
if err != nil {
log.Fatal(err)
}
fmt.Println(personalNote.Text)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
type Note struct {
ID string `storm:"id"`
Text string
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: not found Work related. This is some private text. This is some very personal text.
func (*DB) One ¶
One returns one record by the specified index
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var user User
err := db.One("Email", "john@provider.com", &user)
if err != nil {
log.Fatal(err)
}
// also works on unindexed fields
err = db.One("Name", "John", &user)
if err != nil {
log.Fatal(err)
}
err = db.One("Name", "Jack", &user)
fmt.Println(err)
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: not found
func (*DB) PrefixScan ¶
PrefixScan scans the root buckets for keys matching the given prefix.
func (*DB) Range ¶
func (s *DB) Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error
Range returns one or more records by the specified index within the specified range
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/asdine/storm"
)
func main() {
dir, db := prepareDB()
defer os.RemoveAll(dir)
defer db.Close()
var users []User
err := db.Range("Age", 21, 22, &users)
if err != nil {
log.Fatal(err)
}
fmt.Println("Found", len(users))
}
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
type Account struct {
ID int `storm:"id"`
Amount int64
}
func prepareDB() (string, *storm.DB) {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
for i, name := range []string{"John", "Eric", "Dilbert"} {
email := strings.ToLower(name + "@provider.com")
user := User{
Group: "staff",
Email: email,
Name: name,
Age: 21 + i,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
}
for i := int64(0); i < 10; i++ {
account := Account{Amount: 10000}
err := db.Save(&account)
if err != nil {
log.Fatal(err)
}
}
return dir, db
}
Output: Found 2
func (*DB) Remove ¶
Remove deletes a structure from the associated bucket Deprecated: Use DeleteStruct instead.
func (*DB) Save ¶
Save a structure
Example ¶
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
"github.com/asdine/storm"
)
func main() {
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
defer os.RemoveAll(dir)
type User struct {
ID int `storm:"id"`
Group string `storm:"index"`
Email string `storm:"unique"`
Name string
Age int `storm:"index"`
CreatedAt time.Time `storm:"index"`
}
// Open takes an optional list of options as the last argument.
// AutoIncrement will auto-increment integer IDs without existing values.
db, _ := storm.Open(filepath.Join(dir, "storm.db"), storm.AutoIncrement())
defer db.Close()
user := User{
Group: "staff",
Email: "john@provider.com",
Name: "John",
Age: 21,
CreatedAt: time.Now(),
}
err := db.Save(&user)
if err != nil {
log.Fatal(err)
}
fmt.Println(user.ID)
user2 := user
user2.ID = 0
// Save will fail because of the unique constraint on Email
err = db.Save(&user2)
fmt.Println(err)
}
Output: 1 already exists
func (*DB) UpdateField ¶
UpdateField updates a single field
func (*DB) WithBatch ¶ added in v0.5.0
WithBatch returns a new Storm Node with the batch mode enabled.
type Finder ¶
type Finder interface {
// One returns one record by the specified index
One(fieldName string, value interface{}, to interface{}) error
// Find returns one or more records by the specified index
Find(fieldName string, value interface{}, to interface{}, options ...func(q *index.Options)) error
// AllByIndex gets all the records of a bucket that are indexed in the specified index
AllByIndex(fieldName string, to interface{}, options ...func(*index.Options)) error
// All gets all the records of a bucket.
// If there are no records it returns no error and the 'to' parameter is set to an empty slice.
All(to interface{}, options ...func(*index.Options)) error
// Select a list of records that match a list of matchers. Doesn't use indexes.
Select(matchers ...q.Matcher) Query
// Range returns one or more records by the specified index within the specified range
Range(fieldName string, min, max, to interface{}, options ...func(*index.Options)) error
// Count counts all the records of a bucket
Count(data interface{}) (int, error)
}
A Finder can fetch types from BoltDB
type KeyValueStore ¶
type KeyValueStore interface {
// Get a value from a bucket
Get(bucketName string, key interface{}, to interface{}) error
// Set a key/value pair into a bucket
Set(bucketName string, key interface{}, value interface{}) error
// Delete deletes a key from a bucket
Delete(bucketName string, key interface{}) error
// GetBytes gets a raw value from a bucket.
GetBytes(bucketName string, key interface{}) ([]byte, error)
// SetBytes sets a raw value into a bucket.
SetBytes(bucketName string, key interface{}, value []byte) error
}
KeyValueStore can store and fetch values by key
type Node ¶
type Node interface {
Tx
TypeStore
KeyValueStore
BucketScanner
// From returns a new Storm node with a new bucket root below the current.
// All DB operations on the new node will be executed relative to this bucket.
From(addend ...string) Node
// Bucket returns the bucket name as a slice from the root.
// In the normal, simple case this will be empty.
Bucket() []string
// GetBucket returns the given bucket below the current node.
GetBucket(tx *bolt.Tx, children ...string) *bolt.Bucket
// CreateBucketIfNotExists creates the bucket below the current node if it doesn't
// already exist.
CreateBucketIfNotExists(tx *bolt.Tx, bucket string) (*bolt.Bucket, error)
// WithTransaction returns a New Storm node that will use the given transaction.
WithTransaction(tx *bolt.Tx) Node
// Begin starts a new transaction.
Begin(writable bool) (Node, error)
// Codec used by this instance of Storm
Codec() codec.MarshalUnmarshaler
// WithCodec returns a New Storm Node that will use the given Codec.
WithCodec(codec codec.MarshalUnmarshaler) Node
// WithBatch returns a new Storm Node with the batch mode enabled.
WithBatch(enabled bool) Node
}
A Node in Storm represents the API to a BoltDB bucket.
type Query ¶
type Query interface {
// Skip matching records by the given number
Skip(int) Query
// Limit the results by the given number
Limit(int) Query
// Order by the given fields, in descending precedence, left-to-right.
OrderBy(...string) Query
// Reverse the order of the results
Reverse() Query
// Bucket specifies the bucket name
Bucket(string) Query
// Find a list of matching records
Find(interface{}) error
// First gets the first matching record
First(interface{}) error
// Delete all matching records
Delete(interface{}) error
// Count all the matching records
Count(interface{}) (int, error)
// Returns all the records without decoding them
Raw() ([][]byte, error)
// Execute the given function for each raw element
RawEach(func([]byte, []byte) error) error
// Execute the given function for each element
Each(interface{}, func(interface{}) error) error
}
Query is the low level query engine used by Storm. It allows to operate searches through an entire bucket.
type Tx ¶
type Tx interface {
// Commit writes all changes to disk.
Commit() error
// Rollback closes the transaction and ignores all previous updates.
Rollback() error
}
Tx is a transaction
type TypeStore ¶
type TypeStore interface {
Finder
// Init creates the indexes and buckets for a given structure
Init(data interface{}) error
// ReIndex rebuilds all the indexes of a bucket
ReIndex(data interface{}) error
// Save a structure
Save(data interface{}) error
// Update a structure
Update(data interface{}) error
// UpdateField updates a single field
UpdateField(data interface{}, fieldName string, value interface{}) error
// Drop a bucket
Drop(data interface{}) error
// DeleteStruct deletes a structure from the associated bucket
DeleteStruct(data interface{}) error
// Remove deletes a structure from the associated bucket
// Deprecated: Use DeleteStruct instead.
Remove(data interface{}) error
}
TypeStore stores user defined types in BoltDB
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package codec contains sub-packages with different codecs that can be used to encode and decode entities in Storm.
|
Package codec contains sub-packages with different codecs that can be used to encode and decode entities in Storm. |
|
gob
Package gob contains a codec to encode and decode entities in Gob format
|
Package gob contains a codec to encode and decode entities in Gob format |
|
json
Package json contains a codec to encode and decode entities in JSON format
|
Package json contains a codec to encode and decode entities in JSON format |
|
msgpack
Package msgpack contains a codec to encode and decode entities in msgpack format
|
Package msgpack contains a codec to encode and decode entities in msgpack format |
|
protobuf
Package protobuf contains a codec to encode and decode entities in Protocol Buffer Package protobuf is a generated protocol buffer package.
|
Package protobuf contains a codec to encode and decode entities in Protocol Buffer Package protobuf is a generated protocol buffer package. |
|
sereal
Package sereal contains a codec to encode and decode entities using Sereal
|
Package sereal contains a codec to encode and decode entities using Sereal |
|
Package index contains Index engines used to store values and their corresponding IDs
|
Package index contains Index engines used to store values and their corresponding IDs |
|
Package q contains a list of Matchers used to compare struct fields with values
|
Package q contains a list of Matchers used to compare struct fields with values |