Skip to content

Commit

Permalink
Merge pull request #1035 from fatkodima/zrandmember
Browse files Browse the repository at this point in the history
[Redis 6.2] Add ZRANDMEMBER command
  • Loading branch information
byroot committed Oct 10, 2021
2 parents eaf446c + ab83bf1 commit 6e7b38c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
40 changes: 40 additions & 0 deletions lib/redis.rb
Expand Up @@ -1897,6 +1897,46 @@ def zmscore(key, *members)
end
end

# Get one or more random members from a sorted set.
#
# @example Get one random member
# redis.zrandmember("zset")
# # => "a"
# @example Get multiple random members
# redis.zrandmember("zset", 2)
# # => ["a", "b"]
# @example Gem multiple random members with scores
# redis.zrandmember("zset", 2, with_scores: true)
# # => [["a", 2.0], ["b", 3.0]]
#
# @param [String] key
# @param [Integer] count
# @param [Hash] options
# - `:with_scores => true`: include scores in output
#
# @return [nil, String, Array<String>, Array<[String, Float]>]
# - when `key` does not exist or set is empty, `nil`
# - when `count` is not specified, a member
# - when `count` is specified and `:with_scores` is not specified, an array of members
# - when `:with_scores` is specified, an array with `[member, score]` pairs
def zrandmember(key, count = nil, withscores: false, with_scores: withscores)
if with_scores && count.nil?
raise ArgumentError, "count argument must be specified"
end

args = [:zrandmember, key]
args << count if count

if with_scores
args << "WITHSCORES"
block = FloatifyPairs
end

synchronize do |client|
client.call(args, &block)
end
end

# Return a range of members in a sorted set, by index.
#
# @example Retrieve all members from a sorted set
Expand Down
5 changes: 5 additions & 0 deletions lib/redis/distributed.rb
Expand Up @@ -656,6 +656,11 @@ def zscore(key, member)
node_for(key).zscore(key, member)
end

# Get one or more random members from a sorted set.
def zrandmember(key, count = nil, **options)
node_for(key).zrandmember(key, count, **options)
end

# Get the scores associated with the given members in a sorted set.
def zmscore(key, *members)
node_for(key).zmscore(key, *members)
Expand Down
28 changes: 28 additions & 0 deletions test/lint/sorted_sets.rb
Expand Up @@ -358,6 +358,34 @@ def test_zmscore
end
end

def test_zrandmember
target_version("6.2") do
assert_nil r.zrandmember("foo")

r.zadd "foo", 1.0, "s1"
r.zrem "foo", "s1"
assert_nil r.zrandmember("foo")
assert_equal [], r.zrandmember("foo", 1)

r.zadd "foo", 1.0, "s1"
r.zadd "foo", 2.0, "s2"
r.zadd "foo", 3.0, "s3"

3.times do
assert ["s1", "s2", "s3"].include?(r.zrandmember("foo"))
end

assert_equal 2, r.zrandmember("foo", 2).size
assert_equal 3, r.zrandmember("foo", 4).size
assert_equal 5, r.zrandmember("foo", -5).size

r.zrandmember("foo", 2, with_scores: true).each do |(member, score)|
assert ["s1", "s2", "s3"].include?(member)
assert_instance_of Float, score
end
end
end

def test_zremrangebyrank
r.zadd "foo", 10, "s1"
r.zadd "foo", 20, "s2"
Expand Down

0 comments on commit 6e7b38c

Please sign in to comment.