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"]
この問題に対処する1つの方法は、サーバー側の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全体をLuaオブジェクトにコピーするため(メモリを消費するため)、zset内のアイテムの数が非常に多い場合に欠陥があります。ただし、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]スコアが高いものから低いものの順に並べられた、インデックスでソートされたセット内のメンバーの範囲を返します
ルビーに関しては、次のコマンドで実行できます
redis.zrange("zset", 0, -1, :with_scores => true)
# => [["a", 32.0], ["b", 64.0]]
ソースRubyDocs