Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSONQGet + JSON.INDEX ADD #40

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion clients/goredis.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package clients

import (
"fmt"
"strings"

goredis "github.com/go-redis/redis"
"github.com/nitishm/go-rejson/rjs"
"strings"
)

// GoRedis implements ReJSON interface for Go-Redis/Redis Redis client
Expand Down Expand Up @@ -43,6 +44,58 @@ func (r *GoRedis) JSONSet(key string, path string, obj interface{}, opts ...rjs.
return
}

// JSONSetWithIndex used to set a json object
//
// ReJSON syntax:
// JSON.SET <key> <path> <json> <index>
//
func (r *GoRedis) JSONSetWithIndex(key string, path string, obj interface{}, index string) (res interface{}, err error) { // nolint: lll

args := make([]interface{}, 0, 6)

args = append(args, key, path, obj, "INDEX "+index)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandSETINDEX, args...)
if err != nil {
return nil, err
}

args = append([]interface{}{name}, args...)

fmt.Println(args)

res, err = r.Conn.Do(args...).Result()

if err != nil && err.Error() == rjs.ErrGoRedisNil.Error() {
err = nil
}
return
}

// JSONIndexAdd used to set a json object
//
// ReJSON syntax:
// JSON.INDEX ADD <index> <field> <path>
//
func (r *GoRedis) JSONIndexAdd(index string, field string, path string) (res interface{}, err error) { // nolint: lll

args := make([]interface{}, 0, 6)
args = append(args, "ADD", index, field, `$`+path)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandINDEXADD, args...)
if err != nil {
return nil, err
}
args = append([]interface{}{name}, args...)

res, err = r.Conn.Do(args...).Result()

if err != nil && err.Error() == rjs.ErrGoRedisNil.Error() {
err = nil
}
return
}

// JSONGet used to get a json object
//
// ReJSON syntax:
Expand Down Expand Up @@ -78,6 +131,43 @@ func (r *GoRedis) JSONGet(key, path string, opts ...rjs.GetOption) (res interfac
return rjs.StringToBytes(res), err
}

// JSONQGet used to get a json object
//
// ReJSON syntax:
// JSON.QGET <index>
// [params ...]
//Pass params like "@name:Tom"
func (r *GoRedis) JSONQGet(key string, params ...string) (res interface{}, err error) {

args := make([]interface{}, 0)
arrParam := make([]string, 0)
args = append(args, key)

strParam := `'`
for _, param := range params {
arrParam = append(arrParam, param)
}
strParam += strings.Join(arrParam, " ")
strParam += `'`

args = append(args, strParam)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandQGET, args...)
if err != nil {
return nil, err
}

args = append([]interface{}{name}, args...)

res, err = r.Conn.Do(args...).Result()
if err != nil {
fmt.Println(err.Error())
return
}

return rjs.StringToBytes(res), err
}

// JSONMGet used to get path values from multiple keys
//
// ReJSON syntax:
Expand Down
67 changes: 66 additions & 1 deletion clients/redigo.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package clients

import (
"fmt"
"strings"

redigo "github.com/gomodule/redigo/redis"
"github.com/nitishm/go-rejson/rjs"
"strings"
)

// Redigo implements ReJSON interface for GoModule/Redigo Redis client
Expand Down Expand Up @@ -37,6 +38,40 @@ func (r *Redigo) JSONSet(key string, path string, obj interface{}, opts ...rjs.S
return r.Conn.Do(name, args...)
}

// JSONSetWithIndex used to set a json object
//
// ReJSON syntax:
// JSON.SET <key> <path> <json> <index>
//
func (r *Redigo) JSONSetWithIndex(key string, path string, obj interface{}, index string) (res interface{}, err error) {

args := make([]interface{}, 0, 6)
args = append(args, key, path, obj, "INDEX "+index)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandSETINDEX, args...)
if err != nil {
return nil, err
}
return r.Conn.Do(name, args...)
}

// JSONIndexAdd used to set a json object
//
// ReJSON syntax:
// JSON.INDEX ADD <key> <field> <path>
//
func (r *Redigo) JSONIndexAdd(index string, field string, path string) (res interface{}, err error) {

args := make([]interface{}, 0, 6)
args = append(args, "ADD", index, field, `$`+path)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandINDEXADD, args...)
if err != nil {
return nil, err
}
return r.Conn.Do(name, args...)
}

// JSONGet used to get a json object
//
// ReJSON syntax:
Expand Down Expand Up @@ -67,6 +102,36 @@ func (r *Redigo) JSONGet(key, path string, opts ...rjs.GetOption) (res interface
return r.Conn.Do(name, args...)
}

// JSONQGet used to get a json object
//
// ReJSON syntax:
// JSON.QGET <index>
// [params ...]
//
//Pass params like "@name:Tom"
func (r *Redigo) JSONQGet(key string, params ...string) (res interface{}, err error) {

args := make([]interface{}, 0)
arrParam := make([]string, 0)
args = append(args, key)

strParam := `'`
for _, param := range params {
arrParam = append(arrParam, param)
}
strParam += strings.Join(arrParam, " ")
strParam += `'`

args = append(args, strParam)

name, args, err := rjs.CommandBuilder(rjs.ReJSONCommandQGET, args...)
if err != nil {
return nil, err
}

return r.Conn.Do(name, args...)
}

// JSONMGet used to get path values from multiple keys
//
// ReJSON syntax:
Expand Down
45 changes: 45 additions & 0 deletions rejson.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ func NewReJSONHandler() *Handler {
type ReJSON interface {
JSONSet(key, path string, obj interface{}, opts ...rjs.SetOption) (res interface{}, err error)

JSONSetWithIndex(key, path string, obj interface{}, index string) (res interface{}, err error)

JSONGet(key, path string, opts ...rjs.GetOption) (res interface{}, err error)

JSONQGet(key string, params ...string) (res interface{}, err error)

JSONIndexAdd(key, field, path string) (res interface{}, err error)

Comment on lines 17 to +27
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding these methods in ReJSON interface create a separate interface ReJSON2 and embed ReJSON interfaces in it along with the new methods. And create a separate handler for the ReJSON2, so that the new module won't affect the original one.

Something like this:

Suggested change
type ReJSON interface {
JSONSet(key, path string, obj interface{}, opts ...rjs.SetOption) (res interface{}, err error)
JSONSetWithIndex(key, path string, obj interface{}, index string) (res interface{}, err error)
JSONGet(key, path string, opts ...rjs.GetOption) (res interface{}, err error)
JSONQGet(key string, params ...string) (res interface{}, err error)
JSONIndexAdd(key, field, path string) (res interface{}, err error)
type ReJSON2 interface {
ReJSON
JSONSetWithIndex(key, path string, obj interface{}, index string) (res interface{}, err error)
JSONQGet(key string, params ...string) (res interface{}, err error)
JSONIndexAdd(key, field, path string) (res interface{}, err error)
}

JSONMGet(path string, keys ...string) (res interface{}, err error)

JSONDel(key, path string) (res interface{}, err error)
Expand Down Expand Up @@ -71,6 +77,20 @@ func (r *Handler) JSONSet(key string, path string, obj interface{}, opts ...rjs.
return r.implementation.JSONSet(key, path, obj, opts...)
}

// JSONSetWithIndex used to set a json object
//
// ReJSON syntax:
// JSON.SET <key> <path> <json> <index>
//
func (r *Handler) JSONSetWithIndex(key string, path string, obj interface{}, index string) (
res interface{}, err error) {

if r.clientName == rjs.ClientInactive {
return nil, rjs.ErrNoClientSet
}
return r.implementation.JSONSetWithIndex(key, path, obj, index)
}

Comment on lines +85 to +93
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a separate handler for the ReJSON2, and implement the ReJSON2 interface on it.
You can also wrap the original handler and create a new handler for ReJSON2.

// JSONGet used to get a json object
//
// ReJSON syntax:
Expand All @@ -88,6 +108,31 @@ func (r *Handler) JSONGet(key, path string, opts ...rjs.GetOption) (res interfac
return r.implementation.JSONGet(key, path, opts...)
}

// JSONQGet used to get a json object
//
// ReJSON syntax:
// JSON.QGET <index>
// [params ...]
//Pass params like "@name:Tom"
func (r *Handler) JSONQGet(key string, params ...string) (res interface{}, err error) {
if r.clientName == rjs.ClientInactive {
return nil, rjs.ErrNoClientSet
}
return r.implementation.JSONQGet(key, params...)
}

// JSONAddIndex used to get a json object
//
// ReJSON syntax:
// JSON.INDEX ADD <index> <field> <path>
//
func (r *Handler) JSONIndexAdd(index, field, path string) (res interface{}, err error) {
if r.clientName == rjs.ClientInactive {
return nil, rjs.ErrNoClientSet
}
return r.implementation.JSONIndexAdd(index, field, path)
}
Comment on lines +117 to +134
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for all new methods


// JSONMGet used to get path values from multiple keys
//
// ReJSON syntax:
Expand Down
38 changes: 38 additions & 0 deletions rjs/commands.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ func commandJSONSet(argsIn ...interface{}) (argsOut []interface{}, err error) {
return
}

func commandJSONSetWithIndex(argsIn ...interface{}) (argsOut []interface{}, err error) {
key := argsIn[0]
path := argsIn[1]
obj := argsIn[2]
index := argsIn[3]

argsOut = append(argsOut, key, path)

b, err := json.Marshal(obj)
if err != nil {
return nil, err
}
argsOut = append(argsOut, b)
argsOut = append(argsOut, index)

return
}

func commandJSONGet(argsIn ...interface{}) (argsOut []interface{}, err error) {
key := argsIn[0]
path := argsIn[1]
Expand All @@ -43,6 +61,26 @@ func commandJSONGet(argsIn ...interface{}) (argsOut []interface{}, err error) {
return
}

func commandJSONQGet(argsIn ...interface{}) (argsOut []interface{}, err error) {
key := argsIn[0]
params := argsIn[1]
argsOut = append(argsOut, key)
argsOut = append(argsOut, params)
return
}

func commandJSONIndexAdd(argsIn ...interface{}) (argsOut []interface{}, err error) {
add := argsIn[0]
index := argsIn[1]
field := argsIn[2]
path := argsIn[3]
argsOut = append(argsOut, add)
argsOut = append(argsOut, index)
argsOut = append(argsOut, field)
argsOut = append(argsOut, path)
return
}

func commandJSONGeneric(argsIn ...interface{}) (argsOut []interface{}, err error) {
key := argsIn[0]
path := argsIn[1]
Expand Down
9 changes: 9 additions & 0 deletions rjs/constants.go
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const (
ReJSONCommandDEBUG ReJSONCommandID = 17
ReJSONCommandFORGET ReJSONCommandID = 18
ReJSONCommandRESP ReJSONCommandID = 19
ReJSONCommandQGET ReJSONCommandID = 20
ReJSONCommandINDEXADD ReJSONCommandID = 21
ReJSONCommandSETINDEX ReJSONCommandID = 22
Comment on lines +53 to +55
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion to differentiate from others

Suggested change
ReJSONCommandQGET ReJSONCommandID = 20
ReJSONCommandINDEXADD ReJSONCommandID = 21
ReJSONCommandSETINDEX ReJSONCommandID = 22
ReJSON2CommandQGET ReJSONCommandID = 20
ReJSON2CommandINDEXADD ReJSONCommandID = 21
ReJSON2CommandSETINDEX ReJSONCommandID = 22


// JSONSET command Options
SetOptionNX SetOption = "NX"
Expand Down Expand Up @@ -86,12 +89,18 @@ var commandName = map[ReJSONCommandID]string{
ReJSONCommandDEBUG: "JSON.DEBUG",
ReJSONCommandFORGET: "JSON.FORGET",
ReJSONCommandRESP: "JSON.RESP",
ReJSONCommandQGET: "JSON.QGET",
ReJSONCommandINDEXADD: "JSON.INDEX",
ReJSONCommandSETINDEX: "JSON.SET",
}

// commandMux maps command id to their Command Builder functions
var commandMux = map[ReJSONCommandID]CommandBuilderFunc{
ReJSONCommandSET: commandJSONSet,
ReJSONCommandSETINDEX: commandJSONSetWithIndex,
ReJSONCommandGET: commandJSONGet,
ReJSONCommandQGET: commandJSONQGet,
ReJSONCommandINDEXADD: commandJSONIndexAdd,
ReJSONCommandDEL: commandJSONGeneric,
ReJSONCommandMGET: commandJSONMGet,
ReJSONCommandTYPE: commandJSONGeneric,
Expand Down
2 changes: 1 addition & 1 deletion rjs/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (r ReJSONCommandID) Value() int32 {

// TypeSafety checks the validity of the command id
func (r ReJSONCommandID) TypeSafety() error {
if r.Value() < 0 || r.Value() > 19 {
if r.Value() < 0 || r.Value() > 22 {
return fmt.Errorf("error: invalid command id")
}
return nil
Expand Down