README

goriak Build Status codecov Go Report Card

Current version: v3.2.1.
Riak KV version: 2.0 or higher, the latest version of Riak KV is always recommended.

What is goriak?

goriak is a wrapper around riak-go-client (version 1.9.0 or newer is required) to make it easier and more friendly for developers to use Riak KV.

Installation

go get -u gopkg.in/zegl/goriak.v3

Maps (Riak Data Types)

The main feature of goriak is that goriak automatically can marshal/unmarshal your Go types into Riak data types.

Set (Riak Data Types)

In the example below Name will be saved as a register, and Aliases will be a set.

type User struct {
    Name    string
    Aliases []string
}

user := User {
    Name:   "Foo",
    Alises: []string{"Foo", "Bar"},
}

goriak.Bucket("bucket-name", "bucket-type").Set(user).Key("key").Run(c)
Tags

Struct tags can be used to change the name of the item, or to ignore it.

type User struct {
    Name    string   `goriak:"-"`       // Ignore field
    Aliases []string `goriak:"aliases"` // Save as "aliases" in Riak KV
}

Get (Riak Data Types)

The map can later be retreived as a whole:

var res User
goriak.Bucket("bucket-name", "bucket-type").Get("key", &res).Run(c)

Supported Go types

Go Type Riak Type
struct map
string register
[n]byte register
[]byte register
[]slice set
[]slice set
[][]byte set
map map
time.Time register
int [1] register

1: All signed and unsigned integer types are supported.

Golang map types

Supported key types: all integer types, string.
Supported value types: string, []byte.

Helper types

Some actions are more complicated then necessary with the use of the default Go types and MapOperations.

This is why goriak contains the types Counter, Set, Flag and Register. All of these types will help you performing actions such as incrementing a value, or adding/removing items.

Counters

Riak Counters is supported with the special goriak.Counter type.

Example:

type Article struct {
    Title string
    Views *goriak.Counter
}

// Get our object
var article Article
goriak.Bucket("articles", "map").Get("1-hello-world", &article).Run(con)

// Increase views by 1
err := article.Views.Increase(1).Exec(con)

// check err

Counter.Exec(con) will make a lightweight request to Riak, and the counter is the only object that will be updated.

You can also save the changes to your counter with SetMap(), this is useful if you want to change multiple counters at the same time.

Check godoc for more information.

Sets

You can chose to use goriak.Set to help you with Set related actions, such as adding and removing items. goriak.Set also has support for sending incremental actions to Riak so that you don't have to build that functionality yourself.

Example:

type Article struct {
    Title string
    Tags *goriak.Set
}

// Get our object
var article Article
goriak.Bucket("articles", "map").Get("1-hello-world", &article).Run(con)

// Add the tag "animals"
err := article.Tags.AddString("animals").Exec(con)

// check err

Check godoc for more information.

Values

Values can be automatically JSON Marshalled/Unmarshalled by using SetJSON() and GetJSON(). There is also SetRaw() and GetRaw() that works directly on []bytes.

JSON

// Set object
goriak.Bucket("bucket-name", "bucket-type").SetJSON(obj).Key("key").Run(con)

// Get object
goriak.Bucket("bucket-name", "bucket-type").GetJSON("key", &obj).Run(con)

MapOperation

There is a time in everyones life where you need to perform raw MapOperations on your Riak Data Values.

Some operations, such as RemoveFromSet requires a Context to perform the operation. A Context can be retreived from Get by setting a special context type.

type ourType struct {
    Aliases []string

    // The context from Riak will be added if the tag goriakcontext is provided
    Context []byte `goriak:"goriakcontext"`
}

// ... GetMap()

// Works with MapOperation from github.com/basho/riak-go-client
operation := goriak.NewMapOperation()
operation.AddToSet("Aliases", []byte("Baz"))

goriak.MapOperation("bucket-name", "bucket-type", "key", operation, val.Context)

Secondary Indexes

You can set secondary indexes automatically with SetJSON() by using struct tags.

Strings and all signed integer types are supported. Both as-is and in slices.

type User struct {
    Name    string `goriakindex:"nameindex_bin"`
    Aliases []string
}

Indexes can also be used in slices. If you are using a slice every value in the slice will be added to the index.

type User struct {
    Aliases []string `goriakindex:"aliasesindex_bin"`
}

When saved the next time the index will be updated.

KeysInIndex

Keys in a particular index can be retreived with KeysInIndex.

callback := func(item goriak.SecondaryIndexQueryResult) {
    // use item
}

goriak.Bucket("bucket-name", "bucket-type").
    KeysInIndex("nameindex_bin", "Value", callback).
    Run(con)

AddToIndex

An alternative way of setting Secondary Indexes is by using AddToIndex().

goriak.Bucket("bucket-name", "bucket-type").
    SetRaw(data).
    AddToIndex("indexname_bin", "value").
    Run(con)

Documentation

Overview

Package goriak is a Golang driver for Riak KV. Goriak offers simple ways of binding your Go datatypes and values to Riak.

Goriaks specially is dealing with Riak KV Data Types (http://docs.basho.com/riak/kv/2.1.4/developing/data-types/) and allowing Marshal/Unmarshal of Go structs into Riak Maps.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewMapOperation

func NewMapOperation() riak.MapOperation

NewMapOperation returns a new riak.MapOperation that you can for advanced Riak operations

Types

type AllKeysCommand

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

func (*AllKeysCommand) Run

func (c *AllKeysCommand) Run(session *Session) (*Result, error)

type Command

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

Command is the main query builder object

func Bucket

func Bucket(bucket, bucketType string) *Command

Bucket specifies the bucket and bucket type that your following command will be performed on.

func (*Command) AllKeys

func (c *Command) AllKeys(callback func([]string) error) *AllKeysCommand

AllKeys returns all keys in the set bucket. The response will be sent in multiple batches to callback

func (*Command) Delete

func (c *Command) Delete(key string) *DeleteCommand

Delete deletes the value stored as key

func (*Command) Get

func (c *Command) Get(key string, output interface{}) *MapGetCommand

Get retreives a Map from Riak. Get performs automatic conversion from Riak Maps to your Go datatype. See Set() for more information.

func (*Command) GetHyperLogLog

func (c *Command) GetHyperLogLog(key string) *FetchHyperLogLogCommand

func (*Command) GetJSON

func (c *Command) GetJSON(key string, output interface{}) *GetRawCommand

GetJSON is the same as GetRaw, but with automatic JSON unmarshalling

func (*Command) GetRaw

func (c *Command) GetRaw(key string, output *[]byte) *GetRawCommand

GetRaw retreives key as a []byte. The output will be written to output by Run().

func (*Command) KeysInIndex

func (c *Command) KeysInIndex(indexName, indexValue string, callback func(SecondaryIndexQueryResult)) *CommandKeysInIndex

KeysInIndex returns all keys in the index indexName that has the value indexValue The values will be returned to the callbak function When all keys have been returned SecondaryIndexQueryResult.IsComplete will be true

func (*Command) KeysInIndexRange

func (c *Command) KeysInIndexRange(indexName, min, max string, callback func(SecondaryIndexQueryResult)) *CommandKeysInIndex

KeysInIndexRange is similar to KeysInIndex(), but works with with a range of index values

func (*Command) MapOperation

func (c *Command) MapOperation(op riak.MapOperation) *MapOperationCommand

MapOperation takes a riak.MapOperation so that you can run custom commands on your Riak Maps

func (*Command) RegisterRunMiddleware

func (c *Command) RegisterRunMiddleware(middleware RunMiddleware) *Command

RegisterRunMiddleware adds a middleware function that will wrap the execution of the command. Is currently supported by Get, GetRaw, GetJSON, Set, SetRaw, and SetJSON

func (*Command) Set

func (c *Command) Set(val interface{}) *MapSetCommand

Set automatically converts your Go datatype to the equivalent type in Riak

|  Go Type   | Riak Type |
|------------|-----------|
| struct     | map       |
| string     | register  |
| [n]byte    | register  |
| []byte     | register  |
| []slice    | set       |
| []slice    | set       |
| [][]byte   | set       |
| map        | map       |
| time.Time  | register  |

func (*Command) SetJSON

func (c *Command) SetJSON(value interface{}) *SetRawCommand

SetJSON saves value as key in the bucket bucket/bucketType Values can automatically be added to indexes with the struct tag goriakindex

func (*Command) SetRaw

func (c *Command) SetRaw(value []byte) *SetRawCommand

SetRaw allows you to set a []byte directly to Riak. SetRaw gives you full control of the data stored, compared to SetJSON and Set.

func (*Command) UpdateHyperLogLog

func (c *Command) UpdateHyperLogLog() *UpdateHyperLogLogCommand

type CommandKeysInIndex

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

func (*CommandKeysInIndex) IndexContinuation

func (c *CommandKeysInIndex) IndexContinuation(continuation []byte) *CommandKeysInIndex

func (*CommandKeysInIndex) Limit

func (c *CommandKeysInIndex) Limit(limit uint32) *CommandKeysInIndex

Limit sets the limit returned in KeysInIndex A limit of 0 means unlimited

func (*CommandKeysInIndex) Run

func (c *CommandKeysInIndex) Run(session *Session) (*KeysInIndexResult, error)

type ConflictObject

type ConflictObject struct {
	Value        []byte
	VClock       []byte
	LastModified time.Time
}

func (ConflictObject) GetResolved

func (r ConflictObject) GetResolved() ResolvedConflict

GetResolved creates a ResolvedConflict object

type ConflictResolver

type ConflictResolver interface {
	ConflictResolver([]ConflictObject) ResolvedConflict
}

The ConflictResolver interface is used to solve conflicts when using Get() and GetJSON(). All versions will be sent to your ConflictResolver method. Return the (merged) version that you want to keep.

Example
// For this to work you need to activate allow_mult on your bucket type
// http://docs.basho.com/riak/kv/2.2.0/developing/usage/conflict-resolution/

session, _ := Connect(ConnectOpts{
	Address: "127.0.0.1",
})

key := "object-1"

// Save the same object without using .VClock() causing a conflict
_, err := Bucket("bucket", "tests").SetJSON("hello").Key(key).Run(session)

if err != nil {
	log.Println(err)
}

_, err = Bucket("bucket", "tests").SetJSON("worlds of conflicts!").Key(key).Run(session)

if err != nil {
	log.Println(err)
}

// Our conflict resolver object
resolver := func(objs []ConflictObject) ResolvedConflict {
	// Decide how to pick the result. We'll use len() to pick the longest value
	var maxObject ConflictObject
	var maxValue int

	for _, o := range objs {
		if len(o.Value) > maxValue {
			maxObject = o
			maxValue = len(o.Value)
		}
	}

	// Convert directly to a ResolvedConflict object
	return maxObject.GetResolved()
}

// Get your object
var res string
_, err = Bucket("bucket", "tests").
	GetJSON(key, &res).
	ConflictResolver(resolver).
	Run(session)

if err != nil {
	log.Println(err)
}

// res will now contain the longest value
log.Println(res)
Output:

type ConnectOpts

type ConnectOpts struct {
	// Both Address and Addresses should be on the form HOST|IP[:PORT]
	Address   string   // Address to a single Riak host. Will be used in case Addresses is empty
	Addresses []string // Addresses to all Riak hosts.

	// Username and password for connection to servers with secirity enabled
	User     string
	Password string

	// Path to root CA certificate. Required if security is used
	CARootCert string

	// Option to override port. Is set to 8087 by default
	Port uint32
}

ConnectOpts are the available options for connecting to your Riak instance

type Counter

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

Counter is a wapper to handle Riak Counters Counter needs to be initialized by GetMap() to fully function

func NewCounter

func NewCounter() *Counter

NewCounter returns a partial Counter Counters returned by NewCounter() can only be updated with SetMap(). Counter.Exec() will not work on counters returned by NewCounter()

func (*Counter) Exec

func (c *Counter) Exec(client *Session) error

Exec saves changes made to the Counter to Riak Exec only works on Counters initialized by GetMap() If the commad succeeds the counter will be updated with the value in the response from Riak

func (*Counter) Increase

func (c *Counter) Increase(i int64) *Counter

Increase the value in the Counter by i The value in Counter.Value() will be updated directly Increase() will not save the changes to Riak directly

func (Counter) MarshalJSON

func (c Counter) MarshalJSON() ([]byte, error)

MarshalJSON satisfies the JSON interface

func (*Counter) UnmarshalJSON

func (c *Counter) UnmarshalJSON(data []byte) error

UnmarshalJSON satisfies the JSON interface

func (*Counter) Value

func (c *Counter) Value() int64

Value returns the value in the Counter

type DeleteCommand

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

func (*DeleteCommand) Run

func (c *DeleteCommand) Run(session *Session) (*Result, error)

func (*DeleteCommand) WithDw

func (c *DeleteCommand) WithDw(dw uint32) *DeleteCommand

func (*DeleteCommand) WithPr

func (c *DeleteCommand) WithPr(pr uint32) *DeleteCommand

func (*DeleteCommand) WithPw

func (c *DeleteCommand) WithPw(pw uint32) *DeleteCommand

WithPw sets the number of primary nodes that must report back a successful write for the command to be successful.

func (*DeleteCommand) WithR

func (c *DeleteCommand) WithR(r uint32) *DeleteCommand

func (*DeleteCommand) WithW

func (c *DeleteCommand) WithW(w uint32) *DeleteCommand

WithW sets the number of nodes that must report back a successful write for the command to be successful.

type FetchHyperLogLogCommand

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

func (*FetchHyperLogLogCommand) Run

func (*FetchHyperLogLogCommand) WithPr

func (*FetchHyperLogLogCommand) WithR

type Flag

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

func NewFlag

func NewFlag() *Flag

func (*Flag) Exec

func (f *Flag) Exec(client *Session) error

func (Flag) MarshalJSON

func (f Flag) MarshalJSON() ([]byte, error)

MarshalJSON satisfies the JSON interface

func (*Flag) Set

func (f *Flag) Set(val bool) *Flag

func (*Flag) UnmarshalJSON

func (f *Flag) UnmarshalJSON(data []byte) error

UnmarshalJSON satisfies the JSON interface

func (*Flag) Value

func (f *Flag) Value() bool

type GetRawCommand

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

func (*GetRawCommand) ConflictResolver

func (c *GetRawCommand) ConflictResolver(fn func([]ConflictObject) ResolvedConflict) *GetRawCommand

func (*GetRawCommand) Run

func (c *GetRawCommand) Run(session *Session) (*Result, error)

func (*GetRawCommand) WithPr

func (c *GetRawCommand) WithPr(pr uint32) *GetRawCommand

func (*GetRawCommand) WithR

func (c *GetRawCommand) WithR(r uint32) *GetRawCommand

type HyperLogLogResult

type HyperLogLogResult struct {
	Key         string
	NotFound    bool
	Cardinality uint64
}

type KeysInIndexResult

type KeysInIndexResult struct {
	Continuation []byte
}

type MapGetCommand

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

func (*MapGetCommand) Run

func (c *MapGetCommand) Run(session *Session) (*Result, error)

type MapOperationCommand

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

func (*MapOperationCommand) Context

func (c *MapOperationCommand) Context(ctx []byte) *MapOperationCommand

func (*MapOperationCommand) Key

func (*MapOperationCommand) Run

func (c *MapOperationCommand) Run(session *Session) (*Result, error)

type MapSetCommand

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

func (*MapSetCommand) FilterExclude

func (c *MapSetCommand) FilterExclude(path ...string) *MapSetCommand

FilterExclude does the opposite of FilterInclude. See FinterInclude for more info.

func (*MapSetCommand) FilterInclude

func (c *MapSetCommand) FilterInclude(path ...string) *MapSetCommand

FilterInclude adds a include filter to Set(). Call FilterInclude("A") to only include the field A (and children). Can be combined with FilterExclude() to form more complicated patterns. Use FilterInclude or FilterExclude without parameters to include/exclude the root object. If the same field is both included and excluded the include is prioritized.

func (*MapSetCommand) Key

func (c *MapSetCommand) Key(key string) *MapSetCommand

func (*MapSetCommand) Run

func (c *MapSetCommand) Run(session *Session) (*Result, error)

func (*MapSetCommand) WithDw

func (c *MapSetCommand) WithDw(dw uint32) *MapSetCommand

WithDw sets the number of nodes that must report back a successful write to their backend storage for the command to be successful.

func (*MapSetCommand) WithPw

func (c *MapSetCommand) WithPw(pw uint32) *MapSetCommand

WithPw sets the number of primary nodes that must report back a successful write for the command to be successful.

func (*MapSetCommand) WithW

func (c *MapSetCommand) WithW(w uint32) *MapSetCommand

WithW sets the number of nodes that must report back a successful write for the command to be successful.

type Register

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

func NewRegister

func NewRegister() *Register

func (*Register) Exec

func (r *Register) Exec(client *Session) error

func (Register) MarshalJSON

func (r Register) MarshalJSON() ([]byte, error)

MarshalJSON satisfies the JSON interface

func (*Register) Set

func (r *Register) Set(val []byte) *Register

func (*Register) SetString

func (r *Register) SetString(val string) *Register

func (*Register) String

func (r *Register) String() string

func (*Register) UnmarshalJSON

func (r *Register) UnmarshalJSON(data []byte) error

UnmarshalJSON satisfies the JSON interface

func (*Register) Value

func (r *Register) Value() []byte

type ResolvedConflict

type ResolvedConflict struct {
	Value  []byte
	VClock []byte
}

type Result

type Result struct {
	NotFound bool   // Wether or not the item was not found when using Get, GetJSON, or GetRaw.
	Key      string // Returns your automatically generated key when using Set, SetJSON, or SetRaw.
	Context  []byte // Returns the Riak Context used in map operations. Is set when using Get.
}

Result contains your query result data from Run()

type RunMiddleware

type RunMiddleware func(cmd RunMiddlewarer, next func() (*Result, error)) (*Result, error)

type RunMiddlewarer

type RunMiddlewarer interface {
	Key() string
	Bucket() string
	BucketType() string
}

type SecondaryIndexQueryResult

type SecondaryIndexQueryResult struct {
	Key        string
	IsComplete bool
}

SecondaryIndexQueryResult is the items sent to the callback function used by KeysInIndex

type Session

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

Session holds the connection to Riak

func Connect

func Connect(opts ConnectOpts) (*Session, error)

Connect creates a new Riak connection. See ConnectOpts for the available options.

type Set

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

Set is a special type to make it easier to work with Riak Sets in Go.

Example
session, _ := Connect(ConnectOpts{
	Address: "127.0.0.1",
})

type Article struct {
	Tags *Set

	Context []byte `goriak:"goriakcontext"`
}

// Initializing a new Article and the Set within
art := Article{
	Tags: NewSet(),
}

riakKey := "article-1"

// Adding the tags "one" and "two"
art.Tags.AddString("one")
art.Tags.AddString("two")

_, err := Bucket("bucket", "bucketType").Set(art).Key(riakKey).Run(session)

if err != nil {
	// ..
}

// Retreiving from Riak
var getArt Article
_, err = Bucket("bucket", "bucketType").Get(riakKey, &getArt).Run(session)

if err != nil {
	// ..
}

// Adding one extra tag.
// Multiple AddString() and RemoveString() can be chained together before calling Exec().
err = getArt.Tags.AddString("three").Exec(session)

if err != nil {
	// ..
}
Output:

func NewSet

func NewSet() *Set

NewSet returnes a new and empty Set. Sets returned from NewSet() can not be used with Set.Exec()

func (*Set) Add

func (s *Set) Add(add []byte) *Set

Add adds an item to the direct value of the Set. Save the changes to Riak with Set.Exec() or SetMap().

func (*Set) AddString

func (s *Set) AddString(add string) *Set

AddString is a shortcut to Add

func (*Set) Exec

func (s *Set) Exec(client *Session) error

Exec executes the diff created by Add() and Remove(), and saves the data to Riak

func (*Set) Has

func (s *Set) Has(search []byte) bool

Has returns true if search is a value in the set

func (*Set) HasString

func (s *Set) HasString(search string) bool

HasString returns true if search is a value in the set

func (Set) MarshalJSON

func (s Set) MarshalJSON() ([]byte, error)

MarshalJSON satisfies the JSON interface

func (*Set) Remove

func (s *Set) Remove(remove []byte) *Set

Remove deletes an item to the direct value of the Set. Save the changes to Riak with Set.Exec() or SetMap().

func (*Set) RemoveString

func (s *Set) RemoveString(remove string) *Set

RemoveString is a shortcut to Remove

func (*Set) Strings

func (s *Set) Strings() []string

Strings returns the same data as Value(), but encoded as strings

func (*Set) UnmarshalJSON

func (s *Set) UnmarshalJSON(data []byte) error

UnmarshalJSON satisfies the JSON interface

func (*Set) Value

func (s *Set) Value() [][]byte

Value returnes the raw values from the Set

type SetRawCommand

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

func (*SetRawCommand) AddToIndex

func (c *SetRawCommand) AddToIndex(key, value string) *SetRawCommand

func (*SetRawCommand) Key

func (c *SetRawCommand) Key(key string) *SetRawCommand

func (*SetRawCommand) Run

func (c *SetRawCommand) Run(session *Session) (*Result, error)

buildStoreValueCommand completes the building if the StoreValueCommand used by SetRaw and SetJSON

func (*SetRawCommand) WithContext

func (c *SetRawCommand) WithContext(val []byte) *SetRawCommand

func (*SetRawCommand) WithDw

func (c *SetRawCommand) WithDw(val uint32) *SetRawCommand

Durable writes (to backend storage)

func (*SetRawCommand) WithPw

func (c *SetRawCommand) WithPw(val uint32) *SetRawCommand

Primary node writes

func (*SetRawCommand) WithW

func (c *SetRawCommand) WithW(val uint32) *SetRawCommand

Node writes

type UpdateHyperLogLogCommand

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

func (*UpdateHyperLogLogCommand) Add

func (*UpdateHyperLogLogCommand) AddMultiple

func (c *UpdateHyperLogLogCommand) AddMultiple(vals ...[]byte) *UpdateHyperLogLogCommand

func (*UpdateHyperLogLogCommand) Key

func (*UpdateHyperLogLogCommand) ReturnBody

func (c *UpdateHyperLogLogCommand) ReturnBody(returnBody bool) *UpdateHyperLogLogCommand

func (*UpdateHyperLogLogCommand) Run

Run executes the command. If ReturnBody() is not set to true the result will be nil.

func (*UpdateHyperLogLogCommand) WithDw

WithDw sets the number of nodes that must report back a successful write to their backend storage for the command to be successful.

func (*UpdateHyperLogLogCommand) WithPw

WithPw sets the number of primary nodes that must report back a successful write for the command to be successful.

func (*UpdateHyperLogLogCommand) WithW

WithW sets the number of nodes that must report back a successful write for the command to be successful.

Directories

Path Synopsis
examples