我需要获得可用于 redis 排序集的所有分数。
redis> ZADD myzset 10 "one"
(integer) 1
redis> ZADD myzset 20 "two"
(integer) 1
redis> ZADD myzset 30 "three"
(integer) 1
现在我想检索 myzset 的所有分数,即。10,20,30。
编辑:由于您之前对值大小的问题并不明显,因此我做了一些额外的研究。
根据当前文档,无法仅从排序集中获得分数。
要获得分数,您需要做的是同时将它们添加到单独的集合中,并在需要时从那里获取它们。
不过,您可能首先应该做的是尝试将您的问题以不同的方式映射到数据结构中。我无法从您的问题中看出您为什么需要获得分数,但可能还有其他方法可以更好地映射到 Redis 的问题。
--
我不确定是否有任何方法可以在不获取密钥的情况下获得所有分数,但ZRANGE
至少会获得您正在寻找的信息;
redis> ZADD myzset 10 "one"
(integer) 1
redis> ZADD myzset 20 "two"
(integer) 1
redis> ZADD myzset 30 "three"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
["one","10","two","20","three","30"]
解决此问题的一种方法是使用服务器端 Lua 脚本。
考虑以下脚本:
local res = {}
local result = {}
local tmp = redis.call( 'zrange', KEYS[1], 0, -1, 'withscores' )
for i=1,#tmp,2 do
res[tmp[i+1]]=true
end
for k,_ in pairs(res) do
table.insert(result,k)
end
return result
您可以使用EVAL命令执行它。
它使用 zrange 命令提取 zset 的内容(带有分数),然后构建一个集合(在 Lua 中用一个表表示)以去除多余的分数,最后构建回复表。所以 zset 的值永远不会通过网络发送。
如果 zset 中的项目数非常多,则此脚本存在缺陷,因为它将整个 zset 复制到 Lua 对象中(因此它占用内存)。但是,很容易更改它以增量迭代 zset(每 20 个项目 20 个项目)。例如:
local res = {}
local result = {}
local n = redis.call( 'zcard', KEYS[1] )
local i=0
while i<n do
local tmp = redis.call( 'zrange', KEYS[1], i, i+20, 'withscores' )
for j=1,#tmp,2 do
res[tmp[j+1]]=true
i = i + 1
end
end
for k,_ in pairs(res) do
table.insert(result,k)
end
return result
请注意,我是 Lua 的新手,所以可能有更优雅的方法来实现相同的目标。
您需要传递可选参数 WITHSCORES。请参阅此处的文档:
ZREVRANGE key start stop [WITHSCORES] 按索引返回排序集中的成员范围,分数从高到低排序
当涉及到 ruby 时,以下命令将执行
redis.zrange("zset", 0, -1, :with_scores => true)
# => [["a", 32.0], ["b", 64.0]]