From e47fbd259cfd6a2501ba663a1e3d4e755caedbfb Mon Sep 17 00:00:00 2001 From: Anuragkillswitch <70265851+Anuragkillswitch@users.noreply.github.com> Date: Mon, 3 Apr 2023 18:49:26 +0530 Subject: [PATCH 1/6] feat: adding zrankwithscore and zrevrankwithscore commands : redis 7.2 --- command.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ commands.go | 13 +++++++++++ commands_test.go | 50 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/command.go b/command.go index 21abe11c64..dd99a0b35a 100644 --- a/command.go +++ b/command.go @@ -4710,3 +4710,64 @@ func (cmd *ClusterShardsCmd) readReply(rd *proto.Reader) error { return nil } + +// ----------------------------------------- + +type RankScore struct { + Rank int64 + Score string +} + +type RankWithScoreCmd struct { + baseCmd + + val RankScore +} + +var _ Cmder = (*RankWithScoreCmd)(nil) + +func NewRankWithScoreCmd(ctx context.Context, args ...interface{}) *RankWithScoreCmd { + return &RankWithScoreCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: args, + }, + } +} + +func (cmd *RankWithScoreCmd) SetVal(val RankScore) { + cmd.val = val +} + +func (cmd *RankWithScoreCmd) Val() RankScore { + return cmd.val +} + +func (cmd *RankWithScoreCmd) Result() (RankScore, error) { + return cmd.val, cmd.err +} + +func (cmd *RankWithScoreCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *RankWithScoreCmd) readReply(rd *proto.Reader) error { + _, err := rd.ReadArrayLen() + if err != nil { + return err + } + + rank, err := rd.ReadInt() + if err != nil { + return err + } + + score, err := rd.ReadString() + if err != nil { + return err + } + + cmd.val = RankScore{Rank: rank, Score: score} + + return nil +} diff --git a/commands.go b/commands.go index 588b3a4f54..9f9903f360 100644 --- a/commands.go +++ b/commands.go @@ -383,6 +383,7 @@ type Cmdable interface { ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd ZRevRank(ctx context.Context, key, member string) *IntCmd + ZRevRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd ZScore(ctx context.Context, key, member string) *FloatCmd ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd ZRandMember(ctx context.Context, key string, count int) *StringSliceCmd @@ -2880,6 +2881,12 @@ func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd { return cmd } +func (c cmdable) ZRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd { + cmd := NewRankWithScoreCmd(ctx, "zrank", key, member, "withscore") + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd { args := make([]interface{}, 2, 2+len(members)) args[0] = "zrem" @@ -2970,6 +2977,12 @@ func (c cmdable) ZRevRank(ctx context.Context, key, member string) *IntCmd { return cmd } +func (c cmdable) ZRevRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd { + cmd := NewRankWithScoreCmd(ctx, "zrevrank", key, member, "withscore") + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) ZScore(ctx context.Context, key, member string) *FloatCmd { cmd := NewFloatCmd(ctx, "zscore", key, member) _ = c(ctx, cmd) diff --git a/commands_test.go b/commands_test.go index 72b2bb23de..fafe59f7b8 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4689,6 +4689,31 @@ var _ = Describe("Commands", func() { Expect(zRank.Val()).To(Equal(int64(0))) }) + It("should ZRankWithScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRankWithScore := client.ZRankWithScore(ctx, "zset", "one") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: "1"})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "two") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: "2"})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "three") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: "3"})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "four") + Expect(zRankWithScore.Err()).To(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{})) + }) + It("should ZRem", func() { err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() Expect(err).NotTo(HaveOccurred()) @@ -4960,6 +4985,31 @@ var _ = Describe("Commands", func() { Expect(zRevRank.Val()).To(Equal(int64(0))) }) + It("should ZRevRankWithScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRevRankWithScore := client.ZRevRankWithScore(ctx, "zset", "one") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: "1"})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "two") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: "2"})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "three") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: "3"})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "four") + Expect(zRevRankWithScore.Err()).To(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{})) + }) + It("should ZScore", func() { zAdd := client.ZAdd(ctx, "zset", redis.Z{Score: 1.001, Member: "one"}) Expect(zAdd.Err()).NotTo(HaveOccurred()) From f87e30d3c1f70eb79b911f9511c604c448c60ce1 Mon Sep 17 00:00:00 2001 From: Anuragkillswitch <70265851+Anuragkillswitch@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:10:40 +0530 Subject: [PATCH 2/6] fix: test for non-existing members --- commands_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands_test.go b/commands_test.go index 36d8bf71c1..35b8df5bf5 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4711,7 +4711,7 @@ var _ = Describe("Commands", func() { zRankWithScore = client.ZRankWithScore(ctx, "zset", "four") Expect(zRankWithScore.Err()).To(HaveOccurred()) - Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{})) + Expect(zRankWithScore.Result()).To(Equal(redis.Nil)) }) It("should ZRem", func() { @@ -5007,7 +5007,7 @@ var _ = Describe("Commands", func() { zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "four") Expect(zRevRankWithScore.Err()).To(HaveOccurred()) - Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{})) + Expect(zRevRankWithScore.Result()).To(Equal(redis.Nil)) }) It("should ZScore", func() { From 72e3c1bacf6b42302120c2b24e8841e5806d893d Mon Sep 17 00:00:00 2001 From: Anuragkillswitch <70265851+Anuragkillswitch@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:19:47 +0530 Subject: [PATCH 3/6] fix: Error check --- commands_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands_test.go b/commands_test.go index 35b8df5bf5..44a8bc3ad3 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4711,7 +4711,7 @@ var _ = Describe("Commands", func() { zRankWithScore = client.ZRankWithScore(ctx, "zset", "four") Expect(zRankWithScore.Err()).To(HaveOccurred()) - Expect(zRankWithScore.Result()).To(Equal(redis.Nil)) + Expect(zRankWithScore.Err()).To(Equal(redis.Nil)) }) It("should ZRem", func() { @@ -5007,7 +5007,7 @@ var _ = Describe("Commands", func() { zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "four") Expect(zRevRankWithScore.Err()).To(HaveOccurred()) - Expect(zRevRankWithScore.Result()).To(Equal(redis.Nil)) + Expect(zRevRankWithScore.Err()).To(Equal(redis.Nil)) }) It("should ZScore", func() { From a858d23a85ae6f4d20639f81a21006ae2d570490 Mon Sep 17 00:00:00 2001 From: Anuragkillswitch <70265851+Anuragkillswitch@users.noreply.github.com> Date: Tue, 18 Apr 2023 20:03:17 +0530 Subject: [PATCH 4/6] fix: string to float --- command.go | 4 ++-- commands_test.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/command.go b/command.go index 4ef3aefdb8..8a71a2adc2 100644 --- a/command.go +++ b/command.go @@ -4729,7 +4729,7 @@ func (cmd *ClusterShardsCmd) readReply(rd *proto.Reader) error { type RankScore struct { Rank int64 - Score string + Score float64 } type RankWithScoreCmd struct { @@ -4776,7 +4776,7 @@ func (cmd *RankWithScoreCmd) readReply(rd *proto.Reader) error { return err } - score, err := rd.ReadString() + score, err := rd.ReadFloat() if err != nil { return err } diff --git a/commands_test.go b/commands_test.go index 44a8bc3ad3..bc055cac08 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4699,15 +4699,15 @@ var _ = Describe("Commands", func() { zRankWithScore := client.ZRankWithScore(ctx, "zset", "one") Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: "1"})) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: 1})) zRankWithScore = client.ZRankWithScore(ctx, "zset", "two") Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: "2"})) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: 2})) zRankWithScore = client.ZRankWithScore(ctx, "zset", "three") Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: "3"})) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: 3})) zRankWithScore = client.ZRankWithScore(ctx, "zset", "four") Expect(zRankWithScore.Err()).To(HaveOccurred()) @@ -4995,15 +4995,15 @@ var _ = Describe("Commands", func() { zRevRankWithScore := client.ZRevRankWithScore(ctx, "zset", "one") Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: "1"})) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: 1})) zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "two") Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: "2"})) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: 2})) zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "three") Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) - Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: "3"})) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: 3})) zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "four") Expect(zRevRankWithScore.Err()).To(HaveOccurred()) From bea6dda1f15c6be3365a97a36a1c882e94e33c44 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Wed, 19 Apr 2023 21:43:58 +0800 Subject: [PATCH 5/6] add ZRankWithScore API for Cmdable interface Signed-off-by: monkey92t --- commands.go | 1 + 1 file changed, 1 insertion(+) diff --git a/commands.go b/commands.go index 7caa1de929..4e4e45f371 100644 --- a/commands.go +++ b/commands.go @@ -373,6 +373,7 @@ type Cmdable interface { ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd ZRank(ctx context.Context, key, member string) *IntCmd + ZRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd From 137b127615cc69b39d6187db0637abed79eae6b8 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Wed, 19 Apr 2023 22:09:10 +0800 Subject: [PATCH 6/6] add notes Signed-off-by: monkey92t --- command.go | 3 +-- commands.go | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/command.go b/command.go index 8a71a2adc2..c2655485d1 100644 --- a/command.go +++ b/command.go @@ -4766,8 +4766,7 @@ func (cmd *RankWithScoreCmd) String() string { } func (cmd *RankWithScoreCmd) readReply(rd *proto.Reader) error { - _, err := rd.ReadArrayLen() - if err != nil { + if err := rd.ReadFixedArrayLen(2); err != nil { return err } diff --git a/commands.go b/commands.go index 4e4e45f371..03055c9049 100644 --- a/commands.go +++ b/commands.go @@ -2886,6 +2886,8 @@ func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd { return cmd } +// ZRankWithScore according to the Redis documentation, if member does not exist +// in the sorted set or key does not exist, it will return a redis.Nil error. func (c cmdable) ZRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd { cmd := NewRankWithScoreCmd(ctx, "zrank", key, member, "withscore") _ = c(ctx, cmd) @@ -2932,6 +2934,8 @@ func (c cmdable) ZRevRange(ctx context.Context, key string, start, stop int64) * return cmd } +// ZRevRangeWithScores according to the Redis documentation, if member does not exist +// in the sorted set or key does not exist, it will return a redis.Nil error. func (c cmdable) ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd { cmd := NewZSliceCmd(ctx, "zrevrange", key, start, stop, "withscores") _ = c(ctx, cmd)