Documentation ¶
Overview ¶
Package badgerhold is an indexing and querying layer on top of a badger DB. The goal is to allow easy, persistent storage and retrieval of Go types. badgerDB is an embedded key-value store, and badgerhold serves a similar use case however with a higher level interface for common uses of Badger.
Go Types ¶
BadgerHold deals directly with Go Types. When inserting data, you pass in your structure directly. When querying data you pass in a pointer to a slice of the type you want to return. By default Gob encoding is used. You can put multiple different types into the same DB file and they (and their indexes) will be stored separately.
err := store.Insert(1234, Item{ Name: "Test Name", Created: time.Now(), }) var result []Item err := store.Find(&result, query)
Indexes ¶
BadgerHold will automatically create an index for any struct fields tags with "badgerholdIndex"
type Item struct { ID int Name string Category string `badgerholdIndex:"Category"` Created time.Time }
The first field specified in query will be used as the index (if one exists).
Queries are chained together criteria that applies to a set of fields:
badgerhold.Where("Name").Eq("John Doe").And("DOB").Lt(time.Now())
Example ¶
package main import ( "fmt" "log" "os" "time" "github.com/betim/badgerhold" "github.com/dgraph-io/badger/v2" ) type Item struct { ID int Category string `badgerholdIndex:"Category"` Created time.Time } func main() { data := []Item{ Item{ ID: 0, Category: "blue", Created: time.Now().Add(-4 * time.Hour), }, Item{ ID: 1, Category: "red", Created: time.Now().Add(-3 * time.Hour), }, Item{ ID: 2, Category: "blue", Created: time.Now().Add(-2 * time.Hour), }, Item{ ID: 3, Category: "blue", Created: time.Now().Add(-20 * time.Minute), }, } dir := tempdir() defer os.RemoveAll(dir) options := badgerhold.DefaultOptions options.Dir = dir options.ValueDir = dir store, err := badgerhold.Open(options) defer store.Close() if err != nil { // handle error log.Fatal(err) } // insert the data in one transaction err = store.Badger().Update(func(tx *badger.Txn) error { for i := range data { err := store.TxInsert(tx, data[i].ID, data[i]) if err != nil { return err } } return nil }) if err != nil { // handle error log.Fatal(err) } // Find all items in the blue category that have been created in the past hour var result []Item err = store.Find(&result, badgerhold.Where("Category").Eq("blue").And("Created").Ge(time.Now().Add(-1*time.Hour))) if err != nil { // handle error log.Fatal(err) } fmt.Println(result[0].ID) }
Output: 3
Index ¶
- Constants
- Variables
- func DefaultDecode(data []byte, value interface{}) error
- func DefaultEncode(value interface{}) ([]byte, error)
- func NextSequence() interface{}
- type AggregateResult
- func (a *AggregateResult) Avg(field string) float64
- func (a *AggregateResult) Count() int
- func (a *AggregateResult) Group(result ...interface{})
- func (a *AggregateResult) Max(field string, result interface{})
- func (a *AggregateResult) Min(field string, result interface{})
- func (a *AggregateResult) Reduction(result interface{})
- func (a *AggregateResult) Sort(field string)
- func (a *AggregateResult) Sum(field string) float64
- type Comparer
- type Criterion
- func (c *Criterion) Eq(value interface{}) *Query
- func (c *Criterion) Ge(value interface{}) *Query
- func (c *Criterion) Gt(value interface{}) *Query
- func (c *Criterion) HasPrefix(prefix string) *Query
- func (c *Criterion) HasSuffix(suffix string) *Query
- func (c *Criterion) In(values ...interface{}) *Query
- func (c *Criterion) IsNil() *Query
- func (c *Criterion) Le(value interface{}) *Query
- func (c *Criterion) Lt(value interface{}) *Query
- func (c *Criterion) MatchFunc(match MatchFunc) *Query
- func (c *Criterion) Ne(value interface{}) *Query
- func (c *Criterion) RegExp(expression *regexp.Regexp) *Query
- func (c *Criterion) String() string
- type DecodeFunc
- type EncodeFunc
- type ErrTypeMismatch
- type Field
- type Index
- type MatchFunc
- type Options
- type Query
- func (q *Query) And(field string) *Criterion
- func (q *Query) Index(indexName string) *Query
- func (q *Query) IsEmpty() bool
- func (q *Query) Limit(amount int) *Query
- func (q *Query) Or(query *Query) *Query
- func (q *Query) Reverse() *Query
- func (q *Query) Skip(amount int) *Query
- func (q *Query) SortBy(fields ...string) *Query
- func (q *Query) String() string
- type RecordAccess
- type Store
- func (s *Store) Badger() *badger.DB
- func (s *Store) Close() error
- func (s *Store) Delete(key, dataType interface{}) error
- func (s *Store) DeleteMatching(dataType interface{}, query *Query) error
- func (s *Store) Find(result interface{}, query *Query) error
- func (s *Store) FindAggregate(dataType interface{}, query *Query, groupBy ...string) ([]*AggregateResult, error)
- func (s *Store) Get(key, result interface{}) error
- func (s *Store) Insert(key, data interface{}) error
- func (s *Store) TxDelete(tx *badger.Txn, key, dataType interface{}) error
- func (s *Store) TxDeleteMatching(tx *badger.Txn, dataType interface{}, query *Query) error
- func (s *Store) TxFind(tx *badger.Txn, result interface{}, query *Query) error
- func (s *Store) TxFindAggregate(tx *badger.Txn, dataType interface{}, query *Query, groupBy ...string) ([]*AggregateResult, error)
- func (s *Store) TxGet(tx *badger.Txn, key, result interface{}) error
- func (s *Store) TxInsert(tx *badger.Txn, key, data interface{}) error
- func (s *Store) TxUpdate(tx *badger.Txn, key interface{}, data interface{}) error
- func (s *Store) TxUpdateMatching(tx *badger.Txn, dataType interface{}, query *Query, ...) error
- func (s *Store) TxUpsert(tx *badger.Txn, key interface{}, data interface{}) error
- func (s *Store) Update(key interface{}, data interface{}) error
- func (s *Store) UpdateMatching(dataType interface{}, query *Query, update func(record interface{}) error) error
- func (s *Store) Upsert(key interface{}, data interface{}) error
- type Storer
Examples ¶
Constants ¶
const ( // BadgerHoldIndexTag is the struct tag used to define an a field as indexable for a badgerhold BadgerHoldIndexTag = "badgerholdIndex" // BadgerholdKeyTag is the struct tag used to define an a field as a key for use in a Find query BadgerholdKeyTag = "badgerholdKey" )
const Key = ""
Key is shorthand for specifying a query to run again the Key in a badgerhold, simply returns "" Where(badgerhold.Key).Eq("testkey")
Variables ¶
var DefaultOptions = Options{ Options: badger.DefaultOptions(""), Encoder: DefaultEncode, Decoder: DefaultDecode, SequenceBandwith: 100, }
DefaultOptions are a default set of options for opening a BadgerHold database Includes badgers own default options
var ErrKeyExists = errors.New("This Key already exists in badgerhold for this type")
ErrKeyExists is the error returned when data is being Inserted for a Key that already exists
var ErrNotFound = errors.New("No data found for this key")
ErrNotFound is returned when no data is found for the given key
var ErrUniqueExists = errors.New("This value cannot be written due to the unique constraint on the field")
ErrUniqueExists is the error thrown when data is being inserted for a unique constraint value that already exists
Functions ¶
func DefaultDecode ¶
DefaultDecode is the default decoding func for badgerhold (Gob)
func DefaultEncode ¶
DefaultEncode is the default encoding func for badgerhold (Gob)
func NextSequence ¶
func NextSequence() interface{}
NextSequence is used to create a sequential key for inserts Inserts a uint64 as the key store.Insert(badgerhold.NextSequence(), data)
Types ¶
type AggregateResult ¶
type AggregateResult struct {
// contains filtered or unexported fields
}
AggregateResult allows you to access the results of an aggregate query
func (*AggregateResult) Avg ¶
func (a *AggregateResult) Avg(field string) float64
Avg returns the average float value of the aggregate grouping panics if the field cannot be converted to an float64
func (*AggregateResult) Count ¶
func (a *AggregateResult) Count() int
Count returns the number of records in the aggregate grouping
func (*AggregateResult) Group ¶
func (a *AggregateResult) Group(result ...interface{})
Group returns the field grouped by in the query
func (*AggregateResult) Max ¶
func (a *AggregateResult) Max(field string, result interface{})
Max Returns the maxiumum value of the Aggregate Grouping, uses the Comparer interface
func (*AggregateResult) Min ¶
func (a *AggregateResult) Min(field string, result interface{})
Min returns the minimum value of the Aggregate Grouping, uses the Comparer interface
func (*AggregateResult) Reduction ¶
func (a *AggregateResult) Reduction(result interface{})
Reduction is the collection of records that are part of the AggregateResult Group
func (*AggregateResult) Sort ¶
func (a *AggregateResult) Sort(field string)
Sort sorts the aggregate reduction by the passed in field in ascending order Sort is called automatically by calls to Min / Max to get the min and max values
func (*AggregateResult) Sum ¶
func (a *AggregateResult) Sum(field string) float64
Sum returns the sum value of the aggregate grouping panics if the field cannot be converted to an float64
type Comparer ¶
Comparer compares a type against the encoded value in the store. The result should be 0 if current==other, -1 if current < other, and +1 if current > other. If a field in a struct doesn't specify a comparer, then the default comparison is used (convert to string and compare) this interface is already handled for standard Go Types as well as more complex ones such as those in time and big an error is returned if the type cannot be compared The concrete type will always be passedin, not a pointer
type Criterion ¶
type Criterion struct {
// contains filtered or unexported fields
}
Criterion is an operator and a value that a given field needs to match on
func Where ¶
Where starts a query for specifying the criteria that an object in the badgerhold needs to match to be returned in a Find result
Query API Example
s.Find(badgerhold.Where("FieldName").Eq(value).And("AnotherField").Lt(AnotherValue). Or(badgerhold.Where("FieldName").Eq(anotherValue)
Since Gobs only encode exported fields, this will panic if you pass in a field with a lower case first letter
type DecodeFunc ¶
DecodeFunc is a function for decoding a value from bytes
type EncodeFunc ¶
EncodeFunc is a function for encoding a value into bytes
type ErrTypeMismatch ¶
type ErrTypeMismatch struct { Value interface{} Other interface{} }
ErrTypeMismatch is the error thrown when two types cannot be compared
func (*ErrTypeMismatch) Error ¶
func (e *ErrTypeMismatch) Error() string
type MatchFunc ¶
type MatchFunc func(ra *RecordAccess) (bool, error)
MatchFunc is a function used to test an arbitrary matching value in a query
type Options ¶
type Options struct { Encoder EncodeFunc Decoder DecodeFunc SequenceBandwith uint64 badger.Options }
Options allows you set different options from the defaults For example the encoding and decoding funcs which default to Gob
type Query ¶
type Query struct {
// contains filtered or unexported fields
}
Query is a chained collection of criteria of which an object in the badgerhold needs to match to be returned an empty query matches against all records
func (*Query) IsEmpty ¶
IsEmpty returns true if the query is an empty query an empty query matches against everything
func (*Query) Limit ¶
Limit sets the maximum number of records that can be returned by a query Setting Limit multiple times, or to a negative value will panic
func (*Query) Or ¶
Or creates another separate query that gets unioned with any other results in the query Or will panic if the query passed in contains a limit or skip value, as they are only allowed on top level queries
func (*Query) Skip ¶
Skip skips the number of records that match all the rest of the query criteria, and does not return them in the result set. Setting skip multiple times, or to a negative value will panic
type RecordAccess ¶
type RecordAccess struct {
// contains filtered or unexported fields
}
RecordAccess allows access to the current record, field or allows running a subquery within a MatchFunc
func (*RecordAccess) Field ¶
func (r *RecordAccess) Field() interface{}
Field is the current field being queried
func (*RecordAccess) Record ¶
func (r *RecordAccess) Record() interface{}
Record is the complete record for a given row in badgerhold
func (*RecordAccess) SubAggregateQuery ¶
func (r *RecordAccess) SubAggregateQuery(query *Query, groupBy ...string) ([]*AggregateResult, error)
SubAggregateQuery allows you to run another aggregate query in the same transaction for each record in a parent query
func (*RecordAccess) SubQuery ¶
func (r *RecordAccess) SubQuery(result interface{}, query *Query) error
SubQuery allows you to run another query in the same transaction for each record in a parent query
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a badgerhold wrapper around a badger DB
func (*Store) Badger ¶
func (s *Store) Badger() *badger.DB
Badger returns the underlying Badger DB the badgerhold is based on
func (*Store) Delete ¶
Delete deletes a record from the bolthold, datatype just needs to be an example of the type stored so that the proper bucket and indexes are updated
func (*Store) DeleteMatching ¶
DeleteMatching deletes all of the records that match the passed in query
func (*Store) Find ¶
Find retrieves a set of values from the badgerhold that matches the passed in query result must be a pointer to a slice. The result of the query will be appended to the passed in result slice, rather than the passed in slice being emptied.
func (*Store) FindAggregate ¶
func (s *Store) FindAggregate(dataType interface{}, query *Query, groupBy ...string) ([]*AggregateResult, error)
FindAggregate returns an aggregate grouping for the passed in query groupBy is optional
func (*Store) Get ¶
Get retrieves a value from badgerhold and puts it into result. Result must be a pointer
func (*Store) Insert ¶
Insert inserts the passed in data into the the badgerhold
If the the key already exists in the badgerhold, then an ErrKeyExists is returned If the data struct has a field tagged as `badgerholdKey` and it is the same type as the Insert key, AND the data struct is passed by reference, AND the key field is currently set to the zero-value for that type, then that field will be set to the value of the insert key.
To use this with badgerhold.NextSequence() use a type of `uint64` for the key field.
func (*Store) TxDelete ¶
TxDelete is the same as Delete except it allows you specify your own transaction
func (*Store) TxDeleteMatching ¶
TxDeleteMatching does the same as DeleteMatching, but allows you to specify your own transaction
func (*Store) TxFind ¶
TxFind allows you to pass in your own badger transaction to retrieve a set of values from the badgerhold
func (*Store) TxFindAggregate ¶
func (s *Store) TxFindAggregate(tx *badger.Txn, dataType interface{}, query *Query, groupBy ...string) ([]*AggregateResult, error)
TxFindAggregate is the same as FindAggregate, but you specify your own transaction groupBy is optional
func (*Store) TxGet ¶
TxGet allows you to pass in your own badger transaction to retrieve a value from the badgerhold and puts it into result
func (*Store) TxInsert ¶
TxInsert is the same as Insert except it allows you specify your own transaction
func (*Store) TxUpdate ¶
TxUpdate is the same as Update except it allows you to specify your own transaction
func (*Store) TxUpdateMatching ¶
func (s *Store) TxUpdateMatching(tx *badger.Txn, dataType interface{}, query *Query, update func(record interface{}) error) error
TxUpdateMatching does the same as UpdateMatching, but allows you to specify your own transaction
func (*Store) TxUpsert ¶
TxUpsert is the same as Upsert except it allows you to specify your own transaction
func (*Store) Update ¶
Update updates an existing record in the badgerhold if the Key doesn't already exist in the store, then it fails with ErrNotFound
func (*Store) UpdateMatching ¶
func (s *Store) UpdateMatching(dataType interface{}, query *Query, update func(record interface{}) error) error
UpdateMatching runs the update function for every record that match the passed in query Note that the type of record in the update func always has to be a pointer