Skip to content

Commit

Permalink
Support NOVALUES parameter for HSCAN
Browse files Browse the repository at this point in the history
Issue #2919

The NOVALUES parameter instructs HSCAN to only return the hash keys,
without values.
  • Loading branch information
gerzse committed Mar 8, 2024
1 parent 65c527c commit 40e1893
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
22 changes: 20 additions & 2 deletions commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1100,8 +1100,26 @@ var _ = Describe("Commands", func() {

keys, cursor, err := client.HScan(ctx, "myhash", 0, "", 0).Result()
Expect(err).NotTo(HaveOccurred())
Expect(keys).NotTo(BeEmpty())
Expect(cursor).NotTo(BeZero())
// If we don't get at least two items back, it's really strange.
Expect(cursor).To(BeNumerically(">=", 2))
Expect(len(keys)).To(BeNumerically(">=", 2))
Expect(keys[0]).To(HavePrefix("key"))
Expect(keys[1]).To(Equal("hello"))
})

It("should HScan without values", func() {
for i := 0; i < 1000; i++ {
sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello")
Expect(sadd.Err()).NotTo(HaveOccurred())
}

keys, cursor, err := client.HScanNoValues(ctx, "myhash", 0, "", 0).Result()
Expect(err).NotTo(HaveOccurred())
// If we don't get at least two items back, it's really strange.
Expect(cursor).To(BeNumerically(">=", 2))
Expect(len(keys)).To(BeNumerically(">=", 2))
Expect(keys[0]).To(HavePrefix("key"))
Expect(keys[1]).To(HavePrefix("key"))
})

It("should ZScan", func() {
Expand Down
15 changes: 15 additions & 0 deletions hash_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type HashCmdable interface {
HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
HVals(ctx context.Context, key string) *StringSliceCmd
HRandField(ctx context.Context, key string, count int) *StringSliceCmd
HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd
Expand Down Expand Up @@ -172,3 +173,17 @@ func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match str
_ = c(ctx, cmd)
return cmd
}

func (c cmdable) HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"hscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
args = append(args, "novalues")
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}
16 changes: 16 additions & 0 deletions iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,22 @@ var _ = Describe("ScanIterator", func() {
Expect(vals).To(HaveLen(71 * 2))
Expect(vals).To(ContainElement("K01"))
Expect(vals).To(ContainElement("K71"))
Expect(vals).To(ContainElement("x"))
})

It("should hscan without values across multiple pages", func() {
Expect(hashSeed(71)).NotTo(HaveOccurred())

var vals []string
iter := client.HScanNoValues(ctx, hashKey, 0, "", 10).Iterator()
for iter.Next(ctx) {
vals = append(vals, iter.Val())
}
Expect(iter.Err()).NotTo(HaveOccurred())
Expect(vals).To(HaveLen(71))
Expect(vals).To(ContainElement("K01"))
Expect(vals).To(ContainElement("K71"))
Expect(vals).NotTo(ContainElement("x"))
})

It("should scan to page borders", func() {
Expand Down

0 comments on commit 40e1893

Please sign in to comment.