Skip to content

Commit db300d1

Browse files
committed
Add the TYPE argument to scan/scan_each, targeting 6.0.0+
1 parent f94a57f commit db300d1

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

lib/redis.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2638,12 +2638,13 @@ def evalsha(*args)
26382638
_eval(:evalsha, args)
26392639
end
26402640

2641-
def _scan(command, cursor, args, match: nil, count: nil, &block)
2641+
def _scan(command, cursor, args, match: nil, count: nil, type: nil, &block)
26422642
# SSCAN/ZSCAN/HSCAN already prepend the key to +args+.
26432643

26442644
args << cursor
26452645
args << "MATCH" << match if match
26462646
args << "COUNT" << count if count
2647+
args << "TYPE" << type if type
26472648

26482649
synchronize do |client|
26492650
client.call([command] + args, &block)
@@ -2658,11 +2659,15 @@ def _scan(command, cursor, args, match: nil, count: nil, &block)
26582659
# @example Retrieve a batch of keys matching a pattern
26592660
# redis.scan(4, :match => "key:1?")
26602661
# # => ["92", ["key:13", "key:18"]]
2662+
# @example Retrieve a batch of keys of a certain type
2663+
# redis.scan(92, :type => "zset")
2664+
# # => ["173", ["sortedset:14", "sortedset:78"]]
26612665
#
26622666
# @param [String, Integer] cursor the cursor of the iteration
26632667
# @param [Hash] options
26642668
# - `:match => String`: only return keys matching the pattern
26652669
# - `:count => Integer`: return count keys at most per iteration
2670+
# - `:type => String`: return keys only of the given type
26662671
#
26672672
# @return [String, Array<String>] the next cursor and all found keys
26682673
def scan(cursor, **options)
@@ -2678,10 +2683,15 @@ def scan(cursor, **options)
26782683
# redis.scan_each(:match => "key:1?") {|key| puts key}
26792684
# # => key:13
26802685
# # => key:18
2686+
# @example Execute block for each key of a type
2687+
# redis.scan_each(:type => "hash") {|key| puts redis.type(key)}
2688+
# # => "hash"
2689+
# # => "hash"
26812690
#
26822691
# @param [Hash] options
26832692
# - `:match => String`: only return keys matching the pattern
26842693
# - `:count => Integer`: return count keys at most per iteration
2694+
# - `:type => String`: return keys only of the given type
26852695
#
26862696
# @return [Enumerator] an enumerator for all found keys
26872697
def scan_each(**options, &block)

test/scanning_test.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ def test_scan_match
5353
end
5454
end
5555

56+
def test_scan_type
57+
target_version "6.0.0" do
58+
r.debug :populate, 1000
59+
r.zadd("foo", [1, "s1", 2, "s2", 3, "s3"])
60+
r.zadd("bar", [6, "s1", 5, "s2", 4, "s3"])
61+
r.hset("baz", "k1", "v1")
62+
63+
cursor = 0
64+
all_keys = []
65+
loop do
66+
cursor, keys = r.scan cursor, type: "zset"
67+
all_keys += keys
68+
break if cursor == "0"
69+
end
70+
71+
assert_equal 2, all_keys.uniq.size
72+
end
73+
end
74+
5675
def test_scan_each_enumerator
5776
target_version "2.7.105" do
5877
r.debug :populate, 1000
@@ -78,6 +97,20 @@ def test_scan_each_enumerator_match
7897
end
7998
end
8099

100+
def test_scan_each_enumerator_type
101+
target_version "6.0.0" do
102+
r.debug :populate, 1000
103+
r.zadd("key:zset", [1, "s1", 2, "s2", 3, "s3"])
104+
r.hset("key:hash:1", "k1", "v1")
105+
r.hset("key:hash:2", "k2", "v2")
106+
107+
keys_from_scan = r.scan_each(type: "hash").to_a.uniq
108+
all_keys = r.keys "key:hash:*"
109+
110+
assert all_keys.sort == keys_from_scan.sort
111+
end
112+
end
113+
81114
def test_scan_each_block
82115
target_version "2.7.105" do
83116
r.debug :populate, 100

0 commit comments

Comments
 (0)