Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Redis 6.2] Add ZRANDMEMBER command #1035

Merged
merged 1 commit into from Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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