golang Redis中JSON数据结构存储与操作插件库go-rejson的使用
Golang Redis中JSON数据结构存储与操作插件库go-rejson的使用
注意事项
目前go-ReJSON仅支持redislabs/rejson版本<=1.0.8。如果您使用更高版本,某些命令可能无法按预期工作。
Go-ReJSON简介
Go-ReJSON是一个用于ReJSON Redis模块的Go客户端。ReJSON是一个Redis模块,实现了ECMA-404 JSON数据交换标准作为原生数据类型,允许在Redis键(文档)中存储、更新和获取JSON值。
ReJSON模块的主要特性
- 完整支持JSON标准
- 使用类似JSONPath的语法选择文档中的元素
- 文档以二进制数据存储在树结构中,可以快速访问子元素
- 为所有JSON值类型提供类型化原子操作
安装
go get github.com/nitishm/go-rejson/v4
使用示例
完整示例代码
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"log"
"github.com/nitishm/go-rejson/v4"
goredis "github.com/go-redis/redis/v8"
"github.com/gomodule/redigo/redis"
)
// Name - 学生姓名
type Name struct {
First string `json:"first,omitempty"`
Middle string `json:"middle,omitempty"`
Last string `json:"last,omitempty"`
}
// Student - 学生对象
type Student struct {
Name Name `json:"name,omitempty"`
Rank int `json:"rank,omitempty"`
}
func Example_JSONSet(rh *rejson.Handler) {
// 创建学生对象
student := Student{
Name: Name{
"Mark",
"S",
"Pronto",
},
Rank: 1,
}
// 将学生对象存储到Redis
res, err := rh.JSONSet("student", ".", student)
if err != nil {
log.Fatalf("Failed to JSONSet")
return
}
if res.(string) == "OK" {
fmt.Printf("Success: %s\n", res)
} else {
fmt.Println("Failed to Set: ")
}
// 从Redis获取学生对象
studentJSON, err := redis.Bytes(rh.JSONGet("student", "."))
if err != nil {
log.Fatalf("Failed to JSONGet")
return
}
// 反序列化JSON数据
readStudent := Student{}
err = json.Unmarshal(studentJSON, &readStudent)
if err != nil {
log.Fatalf("Failed to JSON Unmarshal")
return
}
fmt.Printf("Student read from redis : %#v\n", readStudent)
}
func main() {
var addr = flag.String("Server", "localhost:6379", "Redis server address")
rh := rejson.NewReJSONHandler()
flag.Parse()
// 使用Redigo客户端
conn, err := redis.Dial("tcp", *addr)
if err != nil {
log.Fatalf("Failed to connect to redis-server @ %s", *addr)
}
defer func() {
_, err = conn.Do("FLUSHALL")
err = conn.Close()
if err != nil {
log.Fatalf("Failed to communicate to redis-server @ %v", err)
}
}()
rh.SetRedigoClient(conn)
fmt.Println("Executing Example_JSONSET for Redigo Client")
Example_JSONSet(rh)
// 使用GoRedis客户端
cli := goredis.NewClient(&goredis.Options{Addr: *addr})
defer func() {
if err := cli.FlushAll(context.Background()).Err(); err != nil {
log.Fatalf("goredis - failed to flush: %v", err)
}
if err := cli.Close(); err != nil {
log.Fatalf("goredis - failed to communicate to redis-server: %v", err)
}
}()
rh.SetGoRedisClient(cli)
fmt.Println("\nExecuting Example_JSONSET for GoRedis Client")
Example_JSONSet(rh)
}
代码说明
- 首先定义了两个结构体
Name
和Student
,用于表示学生信息 Example_JSONSet
函数演示了如何使用go-rejson:- 创建一个学生对象
- 使用
JSONSet
方法将对象存储到Redis - 使用
JSONGet
方法从Redis获取数据 - 将获取的JSON数据反序列化为结构体
main
函数展示了如何同时使用Redigo和GoRedis两种Redis客户端
主要方法
JSONSet(key string, path string, obj interface{})
: 将对象存储为Redis中的JSONJSONGet(key string, path string)
: 从Redis获取JSON数据
这个示例展示了go-rejson的基本用法,您可以根据需要扩展功能,如使用更复杂的JSONPath查询、更新部分JSON数据等。
更多关于golang Redis中JSON数据结构存储与操作插件库go-rejson的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang Redis中JSON数据结构存储与操作插件库go-rejson的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-rejson: Redis中JSON数据结构存储与操作指南
go-rejson是一个用于在Redis中存储和操作JSON数据的Golang库,它基于Redis的ReJSON模块。下面我将详细介绍如何使用go-rejson进行JSON数据的存储和操作。
安装
首先需要安装go-rejson库和Redis服务器(确保Redis已加载ReJSON模块):
go get github.com/nitishm/go-rejson/v4
基本使用
1. 初始化连接
package main
import (
"context"
"fmt"
"log"
"github.com/go-redis/redis/v8"
"github.com/nitishm/go-rejson/v4"
)
func main() {
// 创建Redis客户端
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
// 创建ReJSON处理器
rh := rejson.NewReJSONHandler()
rh.SetGoRedisClient(rdb)
ctx := context.Background()
// 测试连接
if _, err := rdb.Ping(ctx).Result(); err != nil {
log.Fatalf("Failed to connect to Redis: %v", err)
}
}
2. 存储JSON数据
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Address struct {
City string `json:"city"`
Country string `json:"country"`
} `json:"address"`
}
func setJSON(rh *rejson.Handler) {
ctx := context.Background()
user := User{
Name: "John Doe",
Age: 30,
Address: struct {
City string `json:"city"`
Country string `json:"country"`
}{
City: "New York",
Country: "USA",
},
}
// 设置JSON对象到Redis
res, err := rh.JSONSet("user:123", ".", user)
if err != nil {
log.Fatalf("Failed to JSONSet: %v", err)
}
if res.(string) == "OK" {
fmt.Println("Success: user:123")
}
}
3. 获取JSON数据
func getJSON(rh *rejson.Handler) {
ctx := context.Background()
var user User
// 获取整个JSON对象
_, err := rh.JSONGet("user:123", ".", &user)
if err != nil {
log.Fatalf("Failed to JSONGet: %v", err)
}
fmt.Printf("User: %+v\n", user)
// 获取特定字段
var name string
_, err = rh.JSONGet("user:123", ".name", &name)
if err != nil {
log.Fatalf("Failed to JSONGet name: %v", err)
}
fmt.Printf("Name: %s\n", name)
}
4. 更新JSON数据
func updateJSON(rh *rejson.Handler) {
ctx := context.Background()
// 更新单个字段
res, err := rh.JSONSet("user:123", ".age", 31)
if err != nil {
log.Fatalf("Failed to update age: %v", err)
}
if res.(string) == "OK" {
fmt.Println("Successfully updated age")
}
// 更新嵌套字段
res, err = rh.JSONSet("user:123", ".address.city", "Boston")
if err != nil {
log.Fatalf("Failed to update city: %v", err)
}
if res.(string) == "OK" {
fmt.Println("Successfully updated city")
}
}
5. 数组操作
func arrayOperations(rh *rejson.Handler) {
ctx := context.Background()
// 创建包含数组的JSON
type Post struct {
Title string `json:"title"`
Tags []string `json:"tags"`
Likes int `json:"likes"`
}
post := Post{
Title: "Go Redis JSON",
Tags: []string{"golang", "redis", "json"},
Likes: 0,
}
_, err := rh.JSONSet("post:1", ".", post)
if err != nil {
log.Fatalf("Failed to JSONSet post: %v", err)
}
// 向数组添加元素
_, err = rh.JSONArrAppend("post:1", ".tags", "database")
if err != nil {
log.Fatalf("Failed to append to array: %v", err)
}
// 获取数组长度
length, err := rh.JSONArrLen("post:1", ".tags")
if err != nil {
log.Fatalf("Failed to get array length: %v", err)
}
fmt.Printf("Tags array length: %d\n", length)
// 获取数组元素
var tags []string
_, err = rh.JSONGet("post:1", ".tags", &tags)
if err != nil {
log.Fatalf("Failed to get tags: %v", err)
}
fmt.Printf("Tags: %v\n", tags)
}
6. 删除操作
func deleteOperations(rh *rejson.Handler) {
ctx := context.Background()
// 删除特定字段
_, err := rh.JSONDel("user:123", ".address.city")
if err != nil {
log.Fatalf("Failed to delete city: %v", err)
}
// 删除整个JSON对象
_, err = rh.JSONDel("post:1", ".")
if err != nil {
log.Fatalf("Failed to delete post: %v", err)
}
}
高级特性
1. 批量操作
func batchOperations(rh *rejson.Handler) {
ctx := context.Background()
// 使用MULTI/EXEC进行批量操作
pipe := rdb.TxPipeline()
rh.JSONSetWithOptions("user:123", ".", User{Name: "Batch User", Age: 25}, rejson.SetOptions{})
rh.JSONSetWithOptions("user:123", ".age", 26, rejson.SetOptions{})
_, err := pipe.Exec(ctx)
if err != nil {
log.Fatalf("Failed batch operations: %v", err)
}
}
2. 设置过期时间
func setWithExpire(rh *rejson.Handler) {
ctx := context.Background()
tempData := map[string]interface{}{
"token": "abc123",
"valid": true,
}
// 设置JSON并添加过期时间
_, err := rh.JSONSet("temp:session", ".", tempData)
if err != nil {
log.Fatalf("Failed to set temp data: %v", err)
}
// 设置60秒过期
if err := rdb.Expire(ctx, "temp:session", 60*time.Second).Err(); err != nil {
log.Fatalf("Failed to set expire: %v", err)
}
}
最佳实践
- 键命名规范:使用冒号分隔的命名空间(如
user:123
,post:456
) - 合理使用路径:
.
表示根路径,.field
表示特定字段 - 错误处理:始终检查返回的错误
- 连接池:重用Redis连接以提高性能
- 数据结构设计:根据查询模式设计JSON结构
go-rejson提供了强大的功能来操作Redis中的JSON数据,结合Redis的高性能和JSON的灵活性,非常适合需要复杂数据结构和快速访问的场景。