peripheral

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2018 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package peripheral provides a secondary index layer for badger key-value store - see examples.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNoIndexNameProvided = fmt.Errorf("no index name provided")
)

error

Functions

func Emit

func Emit(txn *layer.Txn, ix *Index, key, val []byte) (reserr error)

Emit .

Types

type Index

type Index struct {
	// contains filtered or unexported fields
}

Index .

func NewIndex

func NewIndex(name string, indexFn IndexFn) (res *Index)

NewIndex .

Example
db := createDB("", false)
defer db.Close()

indexTags := NewIndex("tags", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	json.Unmarshal(val, &p)
	if len(p.Tags) == 0 {
		return
	}
	for _, v := range p.Tags {
		entries = append(entries, IndexEntry{Index: []byte(v)})
	}
	return
})

indexBy := NewIndex("tags", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	json.Unmarshal(val, &p)
	if p.By == "" {
		return
	}
	entries = append(entries, IndexEntry{Index: []byte(p.By)})
	return
})

sampleIndexBuilder := func(txn *layer.Txn, entries map[string][]byte) error {
	for k, v := range entries {
		// all indexes must be built here,
		// based on document type (v), etc, etc.

		if err := Emit(txn, indexTags, []byte(k), v); err != nil {
			return err
		}
		if err := Emit(txn, indexBy, []byte(k), v); err != nil {
			return err
		}
	}
	return nil
}

func() {
	cmnt := comment{
		ID:   "CMNT::001",
		By:   "Frodo Baggins",
		Text: "Hi!",
		At:   time.Now(),
		Tags: []string{"tech", "golang"},
	}
	js, err := json.Marshal(cmnt)
	fmt.Println(err)

	txn := db.NewTransaction(true)
	defer txn.Discard()

	fmt.Println(txn.Set([]byte(cmnt.ID), js))

	err = txn.CommitWith(sampleIndexBuilder, nil)
	fmt.Println(err)
}()
Output:

<nil>
<nil>
<nil>

type IndexEntry

type IndexEntry struct {
	Index, Val []byte
}

IndexEntry .

type IndexFn

type IndexFn func(key, val []byte) ([]IndexEntry, error)

IndexFn .

type Q

type Q struct {
	Index              string
	Start, End, Prefix []byte
	Skip, Limit        int
	Count              bool
}

Q query parameters

type Res

type Res struct {
	Key, Val []byte
	Index    []byte
}

Res .

func QueryIndex

func QueryIndex(params Q, txn *layer.Txn, forIndexedKeys ...bool) (reslist []Res, rescount int, reserr error)

QueryIndex .

Example
db := createDB("", false)
defer db.Close()

check := func(err interface{}) {
	if err == nil {
		return
	}
	panic(err)
}

indexTags := NewIndex("tags", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	if err := json.Unmarshal(val, &p); err != nil {
		return nil, err
	}
	if len(p.Tags) == 0 {
		return
	}
	for _, v := range p.Tags {
		entries = append(entries, IndexEntry{Index: []byte(v)})
	}
	return
})

indexBy := NewIndex("by", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	if err := json.Unmarshal(val, &p); err != nil {
		return nil, err
	}
	if p.By == "" {
		return
	}
	entries = append(entries, IndexEntry{Index: []byte(p.By)})
	return
})

sampleIndexBuilder := func(txn *layer.Txn, entries map[string][]byte) error {
	for k, v := range entries {
		// all indexes must be built here,
		// based on document type (v), etc, etc.

		if err := Emit(txn, indexTags, []byte(k), v); err != nil {
			return err
		}
		if err := Emit(txn, indexBy, []byte(k), v); err != nil {
			return err
		}
	}
	return nil
}

func() {
	cmnt := comment{
		ID:   "CMNT::001",
		By:   "Frodo Baggins",
		Text: "Hi!",
		At:   time.Now(),
		Tags: []string{"nosql"},
	}
	js, err := json.Marshal(cmnt)
	check(err)

	txn := db.NewTransaction(true)
	defer txn.Discard()

	check(txn.Set([]byte(cmnt.ID), js))

	err = txn.CommitWith(sampleIndexBuilder, nil)
	check(err)
}()

func() {
	cmnt := comment{
		ID:   "CMNT::002",
		By:   "Frodo Baggins",
		Text: "Hi!",
		At:   time.Now(),
		Tags: []string{"nosql", "golang"},
	}
	js, err := json.Marshal(cmnt)
	check(err)

	txn := db.NewTransaction(true)
	defer txn.Discard()

	check(txn.Set([]byte(cmnt.ID), js))

	err = txn.CommitWith(sampleIndexBuilder, nil)
	check(err)
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "tags", Start: []byte("nosql"), Prefix: []byte("nosql")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "tags", Start: []byte("golang"), Prefix: []byte("golang")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "by", Start: []byte("Frodo Baggins"), Prefix: []byte("Frodo Baggins")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()
Output:

2
CMNT::001
CMNT::001
nosql
CMNT::002
CMNT::002
nosql
1
CMNT::002
CMNT::002
golang
2
CMNT::001
CMNT::001
Frodo Baggins
CMNT::002
CMNT::002
Frodo Baggins
Example (With)
db := createDB("", false)
defer db.Close()

check := func(err interface{}) {
	if err == nil {
		return
	}
	panic(err)
}

indexTags := NewIndex("tags", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	if err := json.Unmarshal(val, &p); err != nil {
		return nil, err
	}
	if len(p.Tags) == 0 {
		return
	}
	for _, v := range p.Tags {
		entries = append(entries, IndexEntry{Index: []byte(v)})
	}
	return
})

indexBy := NewIndex("by", func(key, val []byte) (entries []IndexEntry, err error) {
	var p comment
	if err := json.Unmarshal(val, &p); err != nil {
		return nil, err
	}
	if p.By == "" {
		return
	}
	entries = append(entries, IndexEntry{Index: []byte(p.By)})
	return
})

sampleIndexBuilder := func(txn *layer.Txn, entries map[string][]byte) error {
	for k, v := range entries {
		// all indexes must be built here,
		// based on document type (v), etc, etc.

		if err := Emit(txn, indexTags, []byte(k), v); err != nil {
			return err
		}
		if err := Emit(txn, indexBy, []byte(k), v); err != nil {
			return err
		}
	}
	return nil
}

func() {
	cmnt := comment{
		ID:   "CMNT::001",
		By:   "Frodo Baggins",
		Text: "Hi!",
		At:   time.Now(),
		Tags: []string{"nosql"},
	}
	js, err := json.Marshal(cmnt)
	check(err)

	err = db.UpdateWith(func(txn *layer.Txn) error {
		return txn.Set([]byte(cmnt.ID), js)
	}, sampleIndexBuilder)
	check(err)
}()

func() {
	cmnt := comment{
		ID:   "CMNT::002",
		By:   "Frodo Baggins",
		Text: "Hi!",
		At:   time.Now(),
		Tags: []string{"nosql", "golang"},
	}
	js, err := json.Marshal(cmnt)
	check(err)

	err = db.UpdateWith(func(txn *layer.Txn) error {
		return txn.Set([]byte(cmnt.ID), js)
	}, sampleIndexBuilder)
	check(err)
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "tags", Start: []byte("nosql"), Prefix: []byte("nosql")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "tags", Start: []byte("golang"), Prefix: []byte("golang")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()

func() {
	got := make(map[string]Res)
	err := db.View(func(txn *layer.Txn) error {
		r, _, err := QueryIndex(Q{Index: "by", Start: []byte("Frodo Baggins"), Prefix: []byte("Frodo Baggins")}, txn)
		if err != nil {
			return err
		}
		for _, v := range r {
			got[string(v.Key)] = v
		}
		return nil
	})
	check(err)
	fmt.Println(len(got))
	var keys []string
	for k := range got {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		v := got[k]
		fmt.Println(k)
		fmt.Println(string(v.Key))
		fmt.Println(string(v.Index))
	}
}()
Output:

2
CMNT::001
CMNT::001
nosql
CMNT::002
CMNT::002
nosql
1
CMNT::002
CMNT::002
golang
2
CMNT::001
CMNT::001
Frodo Baggins
CMNT::002
CMNT::002
Frodo Baggins

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL