Upgrade the <sorted set> series of commands (#1792)

* Upgrade the <sorted set> series of commands

Signed-off-by: monkey92t <golang@88.com>

* Cancel the Deprecated mark of ZAddNX and ZAddXX

Signed-off-by: monkey92t <golang@88.com>
This commit is contained in:
monkey92t 2021-06-23 18:47:10 +08:00 committed by GitHub
parent 526725c5f8
commit f0b2f90143
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 495 additions and 149 deletions

View File

@ -248,12 +248,25 @@ type Cmdable interface {
BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
// TODO: remove
// ZAddCh
// ZIncr
// ZAddNXCh
// ZAddXXCh
// ZIncrNX
// ZIncrXX
// in v9.
// use ZAddArgs and ZAddArgsIncr.
ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd
ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd
ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd
ZIncr(ctx context.Context, key string, member *Z) *FloatCmd ZIncr(ctx context.Context, key string, member *Z) *FloatCmd
ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd
ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd
@ -272,6 +285,9 @@ type Cmdable interface {
ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd
ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd
ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd
ZRank(ctx context.Context, key, member string) *IntCmd ZRank(ctx context.Context, key, member string) *IntCmd
ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd
ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd
@ -285,6 +301,8 @@ type Cmdable interface {
ZRevRank(ctx context.Context, key, member string) *IntCmd ZRevRank(ctx context.Context, key, member string) *IntCmd
ZScore(ctx context.Context, key, member string) *FloatCmd ZScore(ctx context.Context, key, member string) *FloatCmd
ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd
ZUnion(ctx context.Context, store ZStore) *StringSliceCmd
ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd
ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd
ZDiff(ctx context.Context, keys ...string) *StringSliceCmd ZDiff(ctx context.Context, keys ...string) *StringSliceCmd
ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd
@ -393,7 +411,7 @@ func (c statefulCmdable) Auth(ctx context.Context, password string) *StatusCmd {
return cmd return cmd
} }
// Perform an AUTH command, using the given user and pass. // AuthACL Perform an AUTH command, using the given user and pass.
// Should be used to authenticate the current connection with one of the connections defined in the ACL list // Should be used to authenticate the current connection with one of the connections defined in the ACL list
// when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system. // when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) *StatusCmd { func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) *StatusCmd {
@ -454,7 +472,7 @@ func (c cmdable) Ping(ctx context.Context) *StatusCmd {
return cmd return cmd
} }
func (c cmdable) Quit(ctx context.Context) *StatusCmd { func (c cmdable) Quit(_ context.Context) *StatusCmd {
panic("not implemented") panic("not implemented")
} }
@ -717,7 +735,7 @@ func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCm
return cmd return cmd
} }
// Redis `GET key` command. It returns redis.Nil error when key does not exist. // Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
func (c cmdable) Get(ctx context.Context, key string) *StringCmd { func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "get", key) cmd := NewStringCmd(ctx, "get", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -736,7 +754,7 @@ func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *Str
return cmd return cmd
} }
// An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist). // GetEx An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist).
// Requires Redis >= 6.2.0. // Requires Redis >= 6.2.0.
func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd { func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd {
args := make([]interface{}, 0, 4) args := make([]interface{}, 0, 4)
@ -756,7 +774,7 @@ func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration
return cmd return cmd
} }
// redis-server version >= 6.2.0. // GetDel redis-server version >= 6.2.0.
func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd { func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "getdel", key) cmd := NewStringCmd(ctx, "getdel", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -818,7 +836,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
return cmd return cmd
} }
// Redis `SET key value [expiration]` command. // Set Redis `SET key value [expiration]` command.
// Use expiration for `SETEX`-like behavior. // Use expiration for `SETEX`-like behavior.
// //
// Zero expiration means the key has no expiration time. // Zero expiration means the key has no expiration time.
@ -893,14 +911,14 @@ func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a S
return cmd return cmd
} }
// Redis `SETEX key expiration value` command. // SetEX Redis `SETEX key expiration value` command.
func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd { func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value) cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `SET key value [expiration] NX` command. // SetNX Redis `SET key value [expiration] NX` command.
// //
// Zero expiration means the key has no expiration time. // Zero expiration means the key has no expiration time.
// KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL.
@ -924,7 +942,7 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir
return cmd return cmd
} }
// Redis `SET key value [expiration] XX` command. // SetXX Redis `SET key value [expiration] XX` command.
// //
// Zero expiration means the key has no expiration time. // Zero expiration means the key has no expiration time.
// KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL.
@ -1235,7 +1253,7 @@ func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
return cmd return cmd
} }
// redis-server version >= 6.2.0. // HRandField redis-server version >= 6.2.0.
func (c cmdable) HRandField(ctx context.Context, key string, count int, withValues bool) *StringSliceCmd { func (c cmdable) HRandField(ctx context.Context, key string, count int, withValues bool) *StringSliceCmd {
args := make([]interface{}, 0, 4) args := make([]interface{}, 0, 4)
@ -1528,7 +1546,7 @@ func (c cmdable) SIsMember(ctx context.Context, key string, member interface{})
return cmd return cmd
} }
// Redis `SMISMEMBER key member [member ...]` command. // SMIsMember Redis `SMISMEMBER key member [member ...]` command.
func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd { func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd {
args := make([]interface{}, 2, 2+len(members)) args := make([]interface{}, 2, 2+len(members))
args[0] = "smismember" args[0] = "smismember"
@ -1539,14 +1557,14 @@ func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interfac
return cmd return cmd
} }
// Redis `SMEMBERS key` command output as a slice. // SMembers Redis `SMEMBERS key` command output as a slice.
func (c cmdable) SMembers(ctx context.Context, key string) *StringSliceCmd { func (c cmdable) SMembers(ctx context.Context, key string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "smembers", key) cmd := NewStringSliceCmd(ctx, "smembers", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `SMEMBERS key` command output as a map. // SMembersMap Redis `SMEMBERS key` command output as a map.
func (c cmdable) SMembersMap(ctx context.Context, key string) *StringStructMapCmd { func (c cmdable) SMembersMap(ctx context.Context, key string) *StringStructMapCmd {
cmd := NewStringStructMapCmd(ctx, "smembers", key) cmd := NewStringStructMapCmd(ctx, "smembers", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -1559,28 +1577,28 @@ func (c cmdable) SMove(ctx context.Context, source, destination string, member i
return cmd return cmd
} }
// Redis `SPOP key` command. // SPop Redis `SPOP key` command.
func (c cmdable) SPop(ctx context.Context, key string) *StringCmd { func (c cmdable) SPop(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "spop", key) cmd := NewStringCmd(ctx, "spop", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `SPOP key count` command. // SPopN Redis `SPOP key count` command.
func (c cmdable) SPopN(ctx context.Context, key string, count int64) *StringSliceCmd { func (c cmdable) SPopN(ctx context.Context, key string, count int64) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "spop", key, count) cmd := NewStringSliceCmd(ctx, "spop", key, count)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `SRANDMEMBER key` command. // SRandMember Redis `SRANDMEMBER key` command.
func (c cmdable) SRandMember(ctx context.Context, key string) *StringCmd { func (c cmdable) SRandMember(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "srandmember", key) cmd := NewStringCmd(ctx, "srandmember", key)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `SRANDMEMBER key count` command. // SRandMemberN Redis `SRANDMEMBER key count` command.
func (c cmdable) SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd { func (c cmdable) SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "srandmember", key, count) cmd := NewStringSliceCmd(ctx, "srandmember", key, count)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -2059,7 +2077,7 @@ type ZWithKey struct {
Key string Key string
} }
// ZStore is used as an arg to ZInterStore and ZUnionStore. // ZStore is used as an arg to ZInter/ZInterStore and ZUnion/ZUnionStore.
type ZStore struct { type ZStore struct {
Keys []string Keys []string
Weights []float64 Weights []float64
@ -2067,7 +2085,7 @@ type ZStore struct {
Aggregate string Aggregate string
} }
func (z *ZStore) len() (n int) { func (z ZStore) len() (n int) {
n = len(z.Keys) n = len(z.Keys)
if len(z.Weights) > 0 { if len(z.Weights) > 0 {
n += 1 + len(z.Weights) n += 1 + len(z.Weights)
@ -2078,7 +2096,23 @@ func (z *ZStore) len() (n int) {
return n return n
} }
// Redis `BZPOPMAX key [key ...] timeout` command. func (z ZStore) appendArgs(args []interface{}) []interface{} {
for _, key := range z.Keys {
args = append(args, key)
}
if len(z.Weights) > 0 {
args = append(args, "weights")
for _, weights := range z.Weights {
args = append(args, weights)
}
}
if z.Aggregate != "" {
args = append(args, "aggregate", z.Aggregate)
}
return args
}
// BZPopMax Redis `BZPOPMAX key [key ...] timeout` command.
func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd { func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1) args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmax" args[0] = "bzpopmax"
@ -2092,7 +2126,7 @@ func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...st
return cmd return cmd
} }
// Redis `BZPOPMIN key [key ...] timeout` command. // BZPopMin Redis `BZPOPMIN key [key ...] timeout` command.
func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd { func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1) args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmin" args[0] = "bzpopmin"
@ -2106,96 +2140,169 @@ func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...st
return cmd return cmd
} }
func (c cmdable) zAdd(ctx context.Context, a []interface{}, n int, members ...*Z) *IntCmd { // ZAddArgs WARN: The GT, LT and NX options are mutually exclusive.
for i, m := range members { type ZAddArgs struct {
a[n+2*i] = m.Score NX bool
a[n+2*i+1] = m.Member XX bool
LT bool
GT bool
Ch bool
Members []Z
}
func (c cmdable) zAddArgs(key string, args ZAddArgs, incr bool) []interface{} {
a := make([]interface{}, 0, 6+2*len(args.Members))
a = append(a, "zadd", key)
// The GT, LT and NX options are mutually exclusive.
if args.NX {
a = append(a, "nx")
} else {
if args.XX {
a = append(a, "xx")
} }
cmd := NewIntCmd(ctx, a...) if args.GT {
a = append(a, "gt")
} else if args.LT {
a = append(a, "lt")
}
}
if args.Ch {
a = append(a, "ch")
}
if incr {
a = append(a, "incr")
}
for _, m := range args.Members {
a = append(a, m.Score)
a = append(a, m.Member)
}
return a
}
func (c cmdable) ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd {
cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// Redis `ZADD key score member [score member ...]` command. func (c cmdable) ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd {
cmd := NewFloatCmd(ctx, c.zAddArgs(key, args, true)...)
_ = c(ctx, cmd)
return cmd
}
// TODO: Compatible with v8 api, will be removed in v9.
func (c cmdable) zAdd(ctx context.Context, key string, args ZAddArgs, members ...*Z) *IntCmd {
args.Members = make([]Z, len(members))
for i, m := range members {
args.Members[i] = *m
}
cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...)
_ = c(ctx, cmd)
return cmd
}
// ZAdd Redis `ZADD key score member [score member ...]` command.
func (c cmdable) ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 2 return c.zAdd(ctx, key, ZAddArgs{}, members...)
a := make([]interface{}, n+2*len(members))
a[0], a[1] = "zadd", key
return c.zAdd(ctx, a, n, members...)
} }
// Redis `ZADD key NX score member [score member ...]` command. // ZAddNX Redis `ZADD key NX score member [score member ...]` command.
func (c cmdable) ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 3 return c.zAdd(ctx, key, ZAddArgs{
a := make([]interface{}, n+2*len(members)) NX: true,
a[0], a[1], a[2] = "zadd", key, "nx" }, members...)
return c.zAdd(ctx, a, n, members...)
} }
// Redis `ZADD key XX score member [score member ...]` command. // ZAddXX Redis `ZADD key XX score member [score member ...]` command.
func (c cmdable) ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 3 return c.zAdd(ctx, key, ZAddArgs{
a := make([]interface{}, n+2*len(members)) XX: true,
a[0], a[1], a[2] = "zadd", key, "xx" }, members...)
return c.zAdd(ctx, a, n, members...)
} }
// Redis `ZADD key CH score member [score member ...]` command. // ZAddCh Redis `ZADD key CH score member [score member ...]` command.
// Deprecated: Use
// client.ZAddArgs(ctx, ZAddArgs{
// Ch: true,
// Members: []Z,
// })
// remove in v9.
func (c cmdable) ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 3 return c.zAdd(ctx, key, ZAddArgs{
a := make([]interface{}, n+2*len(members)) Ch: true,
a[0], a[1], a[2] = "zadd", key, "ch" }, members...)
return c.zAdd(ctx, a, n, members...)
} }
// Redis `ZADD key NX CH score member [score member ...]` command. // ZAddNXCh Redis `ZADD key NX CH score member [score member ...]` command.
// Deprecated: Use
// client.ZAddArgs(ctx, ZAddArgs{
// NX: true,
// Ch: true,
// Members: []Z,
// })
// remove in v9.
func (c cmdable) ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 4 return c.zAdd(ctx, key, ZAddArgs{
a := make([]interface{}, n+2*len(members)) NX: true,
a[0], a[1], a[2], a[3] = "zadd", key, "nx", "ch" Ch: true,
return c.zAdd(ctx, a, n, members...) }, members...)
} }
// Redis `ZADD key XX CH score member [score member ...]` command. // ZAddXXCh Redis `ZADD key XX CH score member [score member ...]` command.
// Deprecated: Use
// client.ZAddArgs(ctx, ZAddArgs{
// XX: true,
// Ch: true,
// Members: []Z,
// })
// remove in v9.
func (c cmdable) ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd { func (c cmdable) ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd {
const n = 4 return c.zAdd(ctx, key, ZAddArgs{
a := make([]interface{}, n+2*len(members)) XX: true,
a[0], a[1], a[2], a[3] = "zadd", key, "xx", "ch" Ch: true,
return c.zAdd(ctx, a, n, members...) }, members...)
} }
func (c cmdable) zIncr(ctx context.Context, a []interface{}, n int, members ...*Z) *FloatCmd { // ZIncr Redis `ZADD key INCR score member` command.
for i, m := range members { // Deprecated: Use
a[n+2*i] = m.Score // client.ZAddArgsIncr(ctx, ZAddArgs{
a[n+2*i+1] = m.Member // Members: []Z,
} // })
cmd := NewFloatCmd(ctx, a...) // remove in v9.
_ = c(ctx, cmd)
return cmd
}
// Redis `ZADD key INCR score member` command.
func (c cmdable) ZIncr(ctx context.Context, key string, member *Z) *FloatCmd { func (c cmdable) ZIncr(ctx context.Context, key string, member *Z) *FloatCmd {
const n = 3 return c.ZAddArgsIncr(ctx, key, ZAddArgs{
a := make([]interface{}, n+2) Members: []Z{*member},
a[0], a[1], a[2] = "zadd", key, "incr" })
return c.zIncr(ctx, a, n, member)
} }
// Redis `ZADD key NX INCR score member` command. // ZIncrNX Redis `ZADD key NX INCR score member` command.
// Deprecated: Use
// client.ZAddArgsIncr(ctx, ZAddArgs{
// NX: true,
// Members: []Z,
// })
// remove in v9.
func (c cmdable) ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd { func (c cmdable) ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd {
const n = 4 return c.ZAddArgsIncr(ctx, key, ZAddArgs{
a := make([]interface{}, n+2) NX: true,
a[0], a[1], a[2], a[3] = "zadd", key, "incr", "nx" Members: []Z{*member},
return c.zIncr(ctx, a, n, member) })
} }
// Redis `ZADD key XX INCR score member` command. // ZIncrXX Redis `ZADD key XX INCR score member` command.
// Deprecated: Use
// client.ZAddArgsIncr(ctx, ZAddArgs{
// XX: true,
// Members: []Z,
// })
// remove in v9.
func (c cmdable) ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd { func (c cmdable) ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd {
const n = 4 return c.ZAddArgsIncr(ctx, key, ZAddArgs{
a := make([]interface{}, n+2) XX: true,
a[0], a[1], a[2], a[3] = "zadd", key, "incr", "xx" Members: []Z{*member},
return c.zIncr(ctx, a, n, member) })
} }
func (c cmdable) ZCard(ctx context.Context, key string) *IntCmd { func (c cmdable) ZCard(ctx context.Context, key string) *IntCmd {
@ -2225,18 +2332,7 @@ func (c cmdable) ZIncrBy(ctx context.Context, key string, increment float64, mem
func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd { func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd {
args := make([]interface{}, 0, 3+store.len()) args := make([]interface{}, 0, 3+store.len())
args = append(args, "zinterstore", destination, len(store.Keys)) args = append(args, "zinterstore", destination, len(store.Keys))
for _, key := range store.Keys { args = store.appendArgs(args)
args = append(args, key)
}
if len(store.Weights) > 0 {
args = append(args, "weights")
for _, weight := range store.Weights {
args = append(args, weight)
}
}
if store.Aggregate != "" {
args = append(args, "aggregate", store.Aggregate)
}
cmd := NewIntCmd(ctx, args...) cmd := NewIntCmd(ctx, args...)
cmd.setFirstKeyPos(3) cmd.setFirstKeyPos(3)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -2246,19 +2342,7 @@ func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZSt
func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd { func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd {
args := make([]interface{}, 0, 2+store.len()) args := make([]interface{}, 0, 2+store.len())
args = append(args, "zinter", len(store.Keys)) args = append(args, "zinter", len(store.Keys))
for _, key := range store.Keys { args = store.appendArgs(args)
args = append(args, key)
}
if len(store.Weights) > 0 {
args = append(args, "weights")
for _, weights := range store.Weights {
args = append(args, weights)
}
}
if store.Aggregate != "" {
args = append(args, "aggregate", store.Aggregate)
}
cmd := NewStringSliceCmd(ctx, args...) cmd := NewStringSliceCmd(ctx, args...)
cmd.setFirstKeyPos(2) cmd.setFirstKeyPos(2)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -2268,18 +2352,7 @@ func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd {
func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd { func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd {
args := make([]interface{}, 0, 3+store.len()) args := make([]interface{}, 0, 3+store.len())
args = append(args, "zinter", len(store.Keys)) args = append(args, "zinter", len(store.Keys))
for _, key := range store.Keys { args = store.appendArgs(args)
args = append(args, key)
}
if len(store.Weights) > 0 {
args = append(args, "weights")
for _, weights := range store.Weights {
args = append(args, weights)
}
}
if store.Aggregate != "" {
args = append(args, "aggregate", store.Aggregate)
}
args = append(args, "withscores") args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...) cmd := NewZSliceCmd(ctx, args...)
cmd.setFirstKeyPos(2) cmd.setFirstKeyPos(2)
@ -2339,29 +2412,112 @@ func (c cmdable) ZPopMin(ctx context.Context, key string, count ...int64) *ZSlic
return cmd return cmd
} }
func (c cmdable) zRange(ctx context.Context, key string, start, stop int64, withScores bool) *StringSliceCmd { // ZRangeArgs is all the options of the ZRange command.
args := []interface{}{ // In version> 6.2.0, you can replace the(cmd):
"zrange", // ZREVRANGE,
key, // ZRANGEBYSCORE,
start, // ZREVRANGEBYSCORE,
stop, // ZRANGEBYLEX,
// ZREVRANGEBYLEX.
// Please pay attention to your redis-server version.
//
// Rev, ByScore, ByLex and Offset+Count options require redis-server 6.2.0 and higher.
type ZRangeArgs struct {
Key string
// When the ByScore option is provided, the open interval(exclusive) can be set.
// By default, the score intervals specified by <Start> and <Stop> are closed (inclusive).
// It is similar to the deprecated(6.2.0+) ZRangeByScore command.
// For example:
// ZRangeArgs{
// Key: "example-key",
// Start: "(3",
// Stop: 8,
// ByScore: true,
// }
// cmd: "ZRange example-key (3 8 ByScore" (3 < score <= 8).
//
// For the ByLex option, it is similar to the deprecated(6.2.0+) ZRangeByLex command.
// You can set the <Start> and <Stop> options as follows:
// ZRangeArgs{
// Key: "example-key",
// Start: "[abc",
// Stop: "(def",
// ByLex: true,
// }
// cmd: "ZRange example-key [abc (def ByLex"
//
// For normal cases (ByScore==false && ByLex==false), <Start> and <Stop> should be set to the index range (int).
// You can read the documentation for more information: https://redis.io/commands/zrange
Start interface{}
Stop interface{}
// The ByScore and ByLex options are mutually exclusive.
ByScore bool
ByLex bool
Rev bool
// limit offset count.
Offset int64
Count int64
}
func (z ZRangeArgs) appendArgs(args []interface{}) []interface{} {
// For Rev+ByScore/ByLex, we need to adjust the position of <Start> and <Stop>.
if z.Rev && (z.ByScore || z.ByLex) {
args = append(args, z.Key, z.Stop, z.Start)
} else {
args = append(args, z.Key, z.Start, z.Stop)
} }
if withScores {
args = append(args, "withscores") if z.ByScore {
args = append(args, "byscore")
} else if z.ByLex {
args = append(args, "bylex")
} }
if z.Rev {
args = append(args, "rev")
}
if z.Offset != 0 || z.Count != 0 {
args = append(args, "limit", z.Offset, z.Count)
}
return args
}
func (c cmdable) ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd {
args := make([]interface{}, 0, 9)
args = append(args, "zrange")
args = z.appendArgs(args)
cmd := NewStringSliceCmd(ctx, args...) cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
func (c cmdable) ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd {
args := make([]interface{}, 0, 10)
args = append(args, "zrange")
args = z.appendArgs(args)
args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd { func (c cmdable) ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
return c.zRange(ctx, key, start, stop, false) return c.ZRangeArgs(ctx, ZRangeArgs{
Key: key,
Start: start,
Stop: stop,
})
} }
func (c cmdable) ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd { func (c cmdable) ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd {
cmd := NewZSliceCmd(ctx, "zrange", key, start, stop, "withscores") return c.ZRangeArgsWithScores(ctx, ZRangeArgs{
_ = c(ctx, cmd) Key: key,
return cmd Start: start,
Stop: stop,
})
} }
type ZRangeBy struct { type ZRangeBy struct {
@ -2410,6 +2566,15 @@ func (c cmdable) ZRangeByScoreWithScores(ctx context.Context, key string, opt *Z
return cmd return cmd
} }
func (c cmdable) ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd {
args := make([]interface{}, 0, 10)
args = append(args, "zrangestore", dst)
args = z.appendArgs(args)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd { func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd {
cmd := NewIntCmd(ctx, "zrank", key, member) cmd := NewIntCmd(ctx, "zrank", key, member)
_ = c(ctx, cmd) _ = c(ctx, cmd)
@ -2512,29 +2677,38 @@ func (c cmdable) ZScore(ctx context.Context, key, member string) *FloatCmd {
return cmd return cmd
} }
func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd {
args := make([]interface{}, 0, 2+store.len())
args = append(args, "zunion", len(store.Keys))
args = store.appendArgs(args)
cmd := NewStringSliceCmd(ctx, args...)
cmd.setFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd {
args := make([]interface{}, 0, 3+store.len())
args = append(args, "zunion", len(store.Keys))
args = store.appendArgs(args)
args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...)
cmd.setFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd { func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd {
args := make([]interface{}, 0, 3+store.len()) args := make([]interface{}, 0, 3+store.len())
args = append(args, "zunionstore", dest, len(store.Keys)) args = append(args, "zunionstore", dest, len(store.Keys))
for _, key := range store.Keys { args = store.appendArgs(args)
args = append(args, key)
}
if len(store.Weights) > 0 {
args = append(args, "weights")
for _, weight := range store.Weights {
args = append(args, weight)
}
}
if store.Aggregate != "" {
args = append(args, "aggregate", store.Aggregate)
}
cmd := NewIntCmd(ctx, args...) cmd := NewIntCmd(ctx, args...)
cmd.setFirstKeyPos(3) cmd.setFirstKeyPos(3)
_ = c(ctx, cmd) _ = c(ctx, cmd)
return cmd return cmd
} }
// redis-server version >= 6.2.0. // ZRandMember redis-server version >= 6.2.0.
func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd { func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd {
args := make([]interface{}, 0, 4) args := make([]interface{}, 0, 4)
@ -2549,7 +2723,7 @@ func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withSco
return cmd return cmd
} }
// redis-server version >= 6.2.0. // ZDiff redis-server version >= 6.2.0.
func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd { func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd {
args := make([]interface{}, 2+len(keys)) args := make([]interface{}, 2+len(keys))
args[0] = "zdiff" args[0] = "zdiff"
@ -2564,7 +2738,7 @@ func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd {
return cmd return cmd
} }
// redis-server version >= 6.2.0. // ZDiffWithScores redis-server version >= 6.2.0.
func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd { func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd {
args := make([]interface{}, 3+len(keys)) args := make([]interface{}, 3+len(keys))
args[0] = "zdiff" args[0] = "zdiff"
@ -2580,7 +2754,7 @@ func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd
return cmd return cmd
} }
// redis-server version >=6.2.0. // ZDiffStore redis-server version >=6.2.0.
func (c cmdable) ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd { func (c cmdable) ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd {
args := make([]interface{}, 0, 3+len(keys)) args := make([]interface{}, 0, 3+len(keys))
args = append(args, "zdiffstore", destination, len(keys)) args = append(args, "zdiffstore", destination, len(keys))
@ -2814,7 +2988,7 @@ func (c cmdable) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd {
return cmd return cmd
} }
func (c cmdable) Sync(ctx context.Context) { func (c cmdable) Sync(_ context.Context) {
panic("not implemented") panic("not implemented")
} }
@ -3132,7 +3306,7 @@ func (c cmdable) GeoRadiusStore(
return cmd return cmd
} }
// GeoRadius is a read-only GEORADIUSBYMEMBER_RO command. // GeoRadiusByMember is a read-only GEORADIUSBYMEMBER_RO command.
func (c cmdable) GeoRadiusByMember( func (c cmdable) GeoRadiusByMember(
ctx context.Context, key, member string, query *GeoRadiusQuery, ctx context.Context, key, member string, query *GeoRadiusQuery,
) *GeoLocationCmd { ) *GeoLocationCmd {

View File

@ -2940,6 +2940,42 @@ var _ = Describe("Commands", func() {
}})) }}))
}) })
It("should ZAddArgs", func() {
// Test only the GT+LT options.
added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{
GT: true,
Members: []redis.Z{{Score: 1, Member: "one"}},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(added).To(Equal(int64(1)))
vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result()
Expect(err).NotTo(HaveOccurred())
Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}}))
added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{
GT: true,
Members: []redis.Z{{Score: 2, Member: "one"}},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(added).To(Equal(int64(0)))
vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result()
Expect(err).NotTo(HaveOccurred())
Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}}))
added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{
LT: true,
Members: []redis.Z{{Score: 1, Member: "one"}},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(added).To(Equal(int64(0)))
vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result()
Expect(err).NotTo(HaveOccurred())
Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}}))
})
It("should ZAddNX", func() { It("should ZAddNX", func() {
added, err := client.ZAddNX(ctx, "zset", &redis.Z{ added, err := client.ZAddNX(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -2995,6 +3031,7 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}}))
}) })
// TODO: remove in v9.
It("should ZAddCh", func() { It("should ZAddCh", func() {
changed, err := client.ZAddCh(ctx, "zset", &redis.Z{ changed, err := client.ZAddCh(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3011,6 +3048,7 @@ var _ = Describe("Commands", func() {
Expect(changed).To(Equal(int64(0))) Expect(changed).To(Equal(int64(0)))
}) })
// TODO: remove in v9.
It("should ZAddNXCh", func() { It("should ZAddNXCh", func() {
changed, err := client.ZAddNXCh(ctx, "zset", &redis.Z{ changed, err := client.ZAddNXCh(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3038,6 +3076,7 @@ var _ = Describe("Commands", func() {
}})) }}))
}) })
// TODO: remove in v9.
It("should ZAddXXCh", func() { It("should ZAddXXCh", func() {
changed, err := client.ZAddXXCh(ctx, "zset", &redis.Z{ changed, err := client.ZAddXXCh(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3069,6 +3108,7 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}}))
}) })
// TODO: remove in v9.
It("should ZIncr", func() { It("should ZIncr", func() {
score, err := client.ZIncr(ctx, "zset", &redis.Z{ score, err := client.ZIncr(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3093,6 +3133,7 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}}))
}) })
// TODO: remove in v9.
It("should ZIncrNX", func() { It("should ZIncrNX", func() {
score, err := client.ZIncrNX(ctx, "zset", &redis.Z{ score, err := client.ZIncrNX(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3117,6 +3158,7 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}}))
}) })
// TODO: remove in v9.
It("should ZIncrXX", func() { It("should ZIncrXX", func() {
score, err := client.ZIncrXX(ctx, "zset", &redis.Z{ score, err := client.ZIncrXX(ctx, "zset", &redis.Z{
Score: 1, Score: 1,
@ -3475,6 +3517,68 @@ var _ = Describe("Commands", func() {
}})) }}))
}) })
It("should ZRangeArgs", func() {
added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{
Members: []redis.Z{
{Score: 1, Member: "one"},
{Score: 2, Member: "two"},
{Score: 3, Member: "three"},
{Score: 4, Member: "four"},
},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(added).To(Equal(int64(4)))
zRange, err := client.ZRangeArgs(ctx, redis.ZRangeArgs{
Key: "zset",
Start: 1,
Stop: 4,
ByScore: true,
Rev: true,
Offset: 1,
Count: 2,
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(zRange).To(Equal([]string{"three", "two"}))
zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{
Key: "zset",
Start: "-",
Stop: "+",
ByLex: true,
Rev: true,
Offset: 2,
Count: 2,
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(zRange).To(Equal([]string{"two", "one"}))
zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{
Key: "zset",
Start: "(1",
Stop: "(4",
ByScore: true,
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(zRange).To(Equal([]string{"two", "three"}))
// withScores.
zSlice, err := client.ZRangeArgsWithScores(ctx, redis.ZRangeArgs{
Key: "zset",
Start: 1,
Stop: 4,
ByScore: true,
Rev: true,
Offset: 1,
Count: 2,
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(zSlice).To(Equal([]redis.Z{
{Score: 3, Member: "three"},
{Score: 2, Member: "two"},
}))
})
It("should ZRangeByScore", func() { It("should ZRangeByScore", func() {
err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err() err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -3610,6 +3714,35 @@ var _ = Describe("Commands", func() {
Expect(vals).To(Equal([]redis.Z{})) Expect(vals).To(Equal([]redis.Z{}))
}) })
It("should ZRangeStore", func() {
added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{
Members: []redis.Z{
{Score: 1, Member: "one"},
{Score: 2, Member: "two"},
{Score: 3, Member: "three"},
{Score: 4, Member: "four"},
},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(added).To(Equal(int64(4)))
rangeStore, err := client.ZRangeStore(ctx, "new-zset", redis.ZRangeArgs{
Key: "zset",
Start: 1,
Stop: 4,
ByScore: true,
Rev: true,
Offset: 1,
Count: 2,
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(rangeStore).To(Equal(int64(2)))
zRange, err := client.ZRange(ctx, "new-zset", 0, -1).Result()
Expect(err).NotTo(HaveOccurred())
Expect(zRange).To(Equal([]string{"two", "three"}))
})
It("should ZRank", func() { It("should ZRank", func() {
err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err() err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -3907,6 +4040,45 @@ var _ = Describe("Commands", func() {
Expect(zScore.Val()).To(Equal(float64(1.001))) Expect(zScore.Val()).To(Equal(float64(1.001)))
}) })
It("should ZUnion", func() {
err := client.ZAddArgs(ctx, "zset1", redis.ZAddArgs{
Members: []redis.Z{
{Score: 1, Member: "one"},
{Score: 2, Member: "two"},
},
}).Err()
Expect(err).NotTo(HaveOccurred())
err = client.ZAddArgs(ctx, "zset2", redis.ZAddArgs{
Members: []redis.Z{
{Score: 1, Member: "one"},
{Score: 2, Member: "two"},
{Score: 3, Member: "three"},
},
}).Err()
Expect(err).NotTo(HaveOccurred())
union, err := client.ZUnion(ctx, redis.ZStore{
Keys: []string{"zset1", "zset2"},
Weights: []float64{2, 3},
Aggregate: "sum",
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(union).To(Equal([]string{"one", "three", "two"}))
unionScores, err := client.ZUnionWithScores(ctx, redis.ZStore{
Keys: []string{"zset1", "zset2"},
Weights: []float64{2, 3},
Aggregate: "sum",
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(unionScores).To(Equal([]redis.Z{
{Score: 5, Member: "one"},
{Score: 9, Member: "three"},
{Score: 10, Member: "two"},
}))
})
It("should ZUnionStore", func() { It("should ZUnionStore", func() {
err := client.ZAdd(ctx, "zset1", &redis.Z{Score: 1, Member: "one"}).Err() err := client.ZAdd(ctx, "zset1", &redis.Z{Score: 1, Member: "one"}).Err()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())