golang Riak KV数据库驱动插件库goriak的使用

golang Riak KV数据库驱动插件库goriak的使用

goriak是一个封装了riak-go-client的库,使开发者能更简单友好地使用Riak KV数据库。

安装

作为Go模块(需要Go 1.11或更高版本):

go get github.com/zegl/goriak/v3@v3.2.3

作为Go包:

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

Maps (Riak数据类型)

goriak的主要特性是能自动将Go类型编组/解组到Riak数据类型中。

Set (Riak数据类型)

在下面的示例中,Name将作为register保存,Aliases将作为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)

标签

可以使用结构体标签来改变字段名称或忽略字段。

type User struct {
    Name    string   `goriak:"-"`       // 忽略字段
    Aliases []string `goriak:"aliases"` // 在Riak KV中保存为"aliases"
}

Get (Riak数据类型)

之后可以整体获取map:

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

支持的Go类型

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

1: 支持所有有符号和无符号整数类型。

Golang map类型

支持的键类型: 所有整数类型, string。 支持的值类型: string, []byte

辅助类型

有些操作使用默认的Go类型和MapOperations会过于复杂。因此goriak包含了CounterSetFlagRegister类型。这些类型将帮助你执行诸如增加一个值或添加/删除项目等操作。

计数器

Riak计数器通过特殊的goriak.Counter类型支持。

示例:

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

// 获取对象
var article Article
goriak.Bucket("articles", "map").Get("1-hello-world", &article).Run(con)

// 增加1次浏览
err := article.Views.Increase(1).Exec(con)

// 检查错误

Counter.Exec(con)会向Riak发送一个轻量级请求,只有计数器会被更新。你也可以使用SetMap()保存计数器的更改,这在你想同时更改多个计数器时很有用。

集合

你可以选择使用goriak.Set来帮助你处理集合相关操作,如添加和删除项目。goriak.Set还支持向Riak发送增量操作,这样你就不需要自己构建这个功能。

示例:

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

// 获取对象
var article Article
goriak.Bucket("articles", "map").Get("1-hello-world", &article).Run(con)

// 添加标签"animals"
err := article.Tags.AddString("animals").Exec(con)

// 检查错误

可以使用SetJSON()GetJSON()自动进行JSON编组/解组。还有SetRaw()GetRaw()直接处理[]byte

JSON

// 设置对象
goriak.Bucket("bucket-name", "bucket-type").SetJSON(obj).Key("key").Run(con)

// 获取对象
goriak.Bucket("bucket-name", "bucket-type").GetJSON("key", &obj).Run(con)

MapOperation

有时候你需要对Riak数据值执行原始的MapOperations。有些操作,如RemoveFromSet需要一个Context来执行操作。可以通过设置一个特殊的context类型从Get中获取Context。

type ourType struct {
    Aliases []string

    // 如果提供了goriakcontext标签,Riak的context会被添加
    Context []byte `goriak:"goriakcontext"`
}

// ... GetMap()

// 与github.com/basho/riak-go-client中的MapOperation一起工作
operation := goriak.NewMapOperation()
operation.AddToSet("Aliases", []byte("Baz"))

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

二级索引

你可以使用结构体标签通过SetJSON()自动设置二级索引。支持字符串和所有有符号整数类型,包括切片形式。

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

索引也可以在切片中使用。如果使用切片,切片中的每个值都会被添加到索引中。

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

下次保存时索引会被更新。

KeysInIndex

可以使用KeysInIndex获取特定索引中的键。

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

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

AddToIndex

另一种设置二级索引的方法是使用AddToIndex()

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

更多关于golang Riak KV数据库驱动插件库goriak的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Riak KV数据库驱动插件库goriak的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang Riak KV 数据库驱动插件库 goriak 使用指南

简介

goriak 是一个用于连接和操作 Riak KV 数据库的 Go 语言客户端库。它提供了简单易用的 API 来与 Riak 集群交互,支持基本的 CRUD 操作以及一些高级功能。

安装

使用 go get 安装 goriak:

go get github.com/zegl/goriak/v3

基本使用

1. 连接 Riak

package main

import (
	"context"
	"fmt"
	"log"
	"github.com/zegl/goriak/v3"
)

func main() {
	// 创建连接
	conn, err := goriak.Connect(goriak.ConnectOpts{
		Address: "127.0.0.1", // Riak 服务器地址
		Port:    8087,        // PB 端口
	})
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// 使用连接进行操作...
}

2. 基本 CRUD 操作

存储数据

type User struct {
	Name string
	Age  int
}

func storeData(conn *goriak.Session) {
	user := User{
		Name: "John Doe",
		Age:  30,
	}

	// 存储数据到 bucket "users",key 为 "user1"
	_, err := goriak.Bucket("users", "default").Set(user).Key("user1").Run(conn)
	if err != nil {
		log.Fatal(err)
	}
}

获取数据

func getData(conn *goriak.Session) {
	var user User

	// 从 bucket "users" 获取 key 为 "user1" 的数据
	_, err := goriak.Bucket("users", "default").Get("user1", &user).Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("User: %+v\n", user)
}

更新数据

func updateData(conn *goriak.Session) {
	var user User

	// 先获取当前数据
	_, err := goriak.Bucket("users", "default").Get("user1", &user).Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	// 修改数据
	user.Age = 31

	// 更新存储
	_, err = goriak.Bucket("users", "default").Set(user).Key("user1").Run(conn)
	if err != nil {
		log.Fatal(err)
	}
}

删除数据

func deleteData(conn *goriak.Session) {
	// 删除 key 为 "user1" 的数据
	_, err := goriak.Bucket("users", "default").Delete("user1").Run(conn)
	if err != nil {
		log.Fatal(err)
	}
}

3. 高级功能

使用二级索引 (2i)

func useSecondaryIndex(conn *goriak.Session) {
	// 存储带有索引的数据
	user1 := User{Name: "Alice", Age: 25}
	_, err := goriak.Bucket("users", "default").
		Set(user1).
		Key("alice").
		AddIndex("age_int", 25). // 添加整数索引
		Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	user2 := User{Name: "Bob", Age: 30}
	_, err = goriak.Bucket("users", "default").
		Set(user2).
		Key("bob").
		AddIndex("age_int", 30).
		Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	// 查询年龄在 20-30 之间的用户
	var results []User
	_, err = goriak.Bucket("users", "default").
		IndexQuery("age_int", 20, 30, &results).
		Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Users aged 20-30: %+v\n", results)
}

使用计数器

func useCounter(conn *goriak.Session) {
	// 创建或获取计数器
	counter := goriak.Bucket("counters", "default").Counter("page_views")

	// 增加计数器值
	_, err := counter.Increment(5).Run(conn) // 增加5
	if err != nil {
		log.Fatal(err)
	}

	// 获取当前值
	val, err := counter.Value().Run(conn)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Current counter value: %d\n", val)
}

使用 MapReduce

func useMapReduce(conn *goriak.Session) {
	// 创建 MapReduce 查询
	query := goriak.NewMapReduceQuery().
		Bucket("users").
		Map("function(v) { return [JSON.parse(v.values[0].data).Age]; }").
		Reduce("function(v) { return [v.reduce(function(a, b) { return a + b; })]; }")

	// 执行查询
	var result []int
	_, err := query.Run(conn, &result)
	if err != nil {
		log.Fatal(err)
	}

	if len(result) > 0 {
		fmt.Printf("Total age sum: %d\n", result[0])
	}
}

最佳实践

  1. 连接池管理:goriak 内部维护了连接池,不需要手动管理多个连接。

  2. 错误处理:始终检查返回的错误,Riak 操作可能会因为网络问题或集群状态而失败。

  3. 上下文使用:支持 context 用于超时和取消操作:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

_, err := goriak.Bucket("users", "default").Get("user1", &user).WithContext(ctx).Run(conn)
  1. 批量操作:对于大量数据操作,考虑使用批量接口提高性能。

  2. 数据类型选择:Riak 适合存储非结构化或半结构化数据,复杂查询不是它的强项。

总结

goriak 提供了简单直观的 API 来与 Riak KV 数据库交互,支持基本 CRUD 操作、二级索引、计数器等高级功能。通过合理使用这些功能,可以构建高性能、分布式的数据存储解决方案。

回到顶部