diff --git a/redis/client.py b/redis/client.py index 57932b9f73..a582f676e3 100755 --- a/redis/client.py +++ b/redis/client.py @@ -2943,6 +2943,28 @@ def zpopmin(self, name, count=None): } return self.execute_command('ZPOPMIN', name, *args, **options) + def zrandmember(self, key, count=None, withscores=False): + """ + Return a random element from the sorted set value stored at key. + + ``count`` if the argument is positive, return an array of distinct + fields. If called with a negative count, the behavior changes and + the command is allowed to return the same field multiple times. + In this case, the number of returned fields is the absolute value + of the specified count. + + ``withscores`` The optional WITHSCORES modifier changes the reply so it + includes the respective scores of the randomly selected elements from + the sorted set. + """ + params = [] + if count is not None: + params.append(count) + if withscores: + params.append("WITHSCORES") + + return self.execute_command("ZRANDMEMBER", key, *params) + def bzpopmax(self, keys, timeout=0): """ ZPOPMAX a value off of the first non-empty sorted set diff --git a/tests/test_commands.py b/tests/test_commands.py index 27117e3188..6827681684 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1506,6 +1506,18 @@ def test_zpopmin(self, r): assert r.zpopmin('a', count=2) == \ [(b'a2', 2), (b'a3', 3)] + @skip_if_server_version_lt('6.2.0') + def test_zrandemember(self, r): + r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) + assert r.zrandmember('a') is not None + assert len(r.zrandmember('a', 2)) == 2 + # with scores + assert len(r.zrandmember('a', 2, True)) == 4 + # without duplications + assert len(r.zrandmember('a', 10)) == 5 + # with duplications + assert len(r.zrandmember('a', -10)) == 10 + @skip_if_server_version_lt('4.9.0') def test_bzpopmax(self, r): r.zadd('a', {'a1': 1, 'a2': 2})