Redis: получить все оценки доступны для отсортированного набора

Мне нужно получить все оценки, доступные для отсортированного набора 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.

4 ответов


один из способов решить эту проблему-использовать сценарии 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

Вы можете выполнить его с помощью оценку.

он использует команду 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, поэтому, возможно, есть более элегантные способы достичь того же самого.


редактировать: поскольку ваша проблема с размером значений не была очевидной раньше, я провел некоторые дополнительные исследования.

в соответствии с текущей документацией нет способа получить только баллы из отсортированного набора.

что вам нужно сделать, чтобы получить только баллы, это одновременно добавить их в отдельный набор и получить их оттуда, когда это необходимо.

что вы, вероятно, должны сделать сначала, хотя это попытаться отобразить вашу проблему по-другому в структуры данных. Я не могу сказать из вашего вопроса, Почему вам нужно получить баллы, но могут быть другие способы структурировать проблему, которая будет лучше соответствовать 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"]

вам нужно передать необязательный аргумент WITHSCORES. Ознакомиться с документацией здесь:

zrevrange key start stop [WITHSCORES] возвращает диапазон членов в сортированный набор, по индексу, с баллами, упорядоченными от высокого до низкого


когда дело доходит до ruby, следующая команда будет делать

redis.zrange("zset", 0, -1, :with_scores => true)
# => [["a", 32.0], ["b", 64.0]]

источник Ruby Docs