Получить индекс элемента по значению в списке redis
У меня есть список redis, который я создал, я использую его как очередь в тот момент, который меняет время от времени. Моя проблема заключается в том, что я хотел бы получить индекс элемента в этой очереди/списке по значению.
Пример
Если у меня есть список со следующими значениями:
{"dan","eduardo","pedro"}
Индексы будут:
0 : "dan"
1 : "eduardo"
2 : "pedro"
Я хочу уметь, передав значение, чтобы получить индекс этого значения в моем списке.
Как "eduardo" и верните "1".
Возможно ли, если так, как бы вы это сделали?
Также я должен сказать, что я выполняю команды очереди в свой список, удаляя элементы сверху и добавляя их внизу.
В настоящее время я использую node.js 0.6.6 и последний модуль redis с последней версией версии 2.4.4.
Я рад за решение только в redis-cli.
Кроме того, нет никакого ограничения, но это должно быть возможно сделать с помощью redis в отдельности, без внешнего процесса и т.д. Однако, если вы хотите использовать команду EVAL с lua для этого.
Изменить
Также я думаю, что мой ответ может быть на отсортированных наборах не в очереди.
Ответы
Ответ 1
Я не знаю данных узла nodejs для этого, но ниже приведена реализация очень простой команды indexOf в lua.
В моем файле indexof.lua
у меня есть следующий код:
local key = KEYS[1]
local obj = ARGV[1]
local items = redis.call('lrange', key, 0, -1)
for i=1,#items do
if items[i] == obj then
return i - 1
end
end
return -1
Давайте нажмем несколько значений на mylist
.
> rpush mylist foo bar baz qux
(integer) 4
Мы можем использовать lua script, чтобы найти индекс любого значения в списке. Команда O (N).
$ redis-cli --eval indexof.lua mylist , bar
(integer) 1
индекс bar
был 1
> lindex mylist 1
"bar"
индекс nil
равен -1
$ redis-cli --eval indexof.lua mylist , nil
(integer) -1
Посмотрите http://redis.io/commands/eval дополнительную документацию по команде EVAL.
Ответ 2
Используйте отсортированные наборы для реализации очереди.
Добавьте участников и используйте метку времени в качестве оценки.
> ZADD queue 1326990501 foo 1326990502 bar 1326990503 baz 1326990504 qux
(integer) 4
Вы можете возвращать члены в порядке FIFO и LIFO с помощью ZRANGE и ZREVRANGE соответственно.
FIFO:
> ZRANGE queue 0 0
"foo"
LIFO:
> ZREVRANGE queue 0 0
"qux"
Чтобы найти индекс члена, используйте ZRANK. ZRANK op - O (log (N))
> ZRANK queue bar
(integer) 1
Ответ 3
Как вы можете сказать, Redis не поддерживает такую операцию (грустное лицо).
Хотя кто-то сделал несколько хороших замечаний о том, почему такая операция имеет смысл, похоже, что Salvatore не будет реализовывать ее в ближайшее время.
В основном два метода обхода (как указывалось другими ответами):
- Используйте пользовательский lua script, чтобы найти индекс в списке;
- Используйте отсортированный набор (вместо списка) с меткой времени в качестве оценки и
ZRANK
для индекса.
Так как первая O(N)
, а последняя просто O(log(N))
, вы, вероятно, можете сказать, какая из них превосходит другую.
В любом случае я решил поставить тест *:
╔════════════════╦═══════════════════════╦══════════════════════╗
║ ║ Sorted Set with ZRANK ║ List with lua script ║
╠════════════════╬═══════════════════════╬══════════════════════╣
║ 1000 elements ║ 0.0638264 seconds ║ 0.2723238 seconds ║
╠════════════════╬═══════════════════════╬══════════════════════╣
║ 10000 elements ║ 00.4484714 seconds ║ 41.0661683 seconds ║
╚════════════════╩═══════════════════════╩══════════════════════╝
Yup, это ошеломляет 41 секунду всего за десять тысяч элементов.
* В Windows 7 Redis 2.8 (Порт MSOpenTech),.NET 4 с включенной оптимизацией компилятора и StackExchange.Redis 1.0.488.
Ответ 4
В соответствии с билетом 140 в списке выпусков redis.io
Запрос функции: lRank
"Привет, эта команда, скорее всего, не будет реализована, поскольку она является как командой O (N), так и той, которая обычно ощущается по мере необходимости, только когда в дизайне макета данных есть некоторая ошибка". Salvatore Sanfilippo на https://github.com/antirez/redis/issues/140.
Я не совсем уверен, почему и как хотелось бы узнать индекс элемента по значению, может быть ошибкой в дизайне данных. Однако он дает понять, что вы можете использовать код lua и/или отсортированные наборы.
Таким образом, это означает, что нет способа найти индекс элемента в списке, отличном от , используя lua script.
Однако в зависимости от реализации, то есть проектирования данных, лучше рассмотреть отсортированные наборы вместо списков.
Ответ 5
Используя отсортированные наборы (ZADD и т.д.), вы можете использовать ZRANK.
Изменить: мой старый ответ ниже не работает, потому что ваш список изменяется, хотя он и есть, со списком, который растет только с помощью RPUSH.
Вы можете сохранить индекс со значением (или его хешем) в качестве ключа:
set listvalue listindex
Чтобы ваш redis был организован, вы можете префикс этих ключей с именем list:
set listname:listvalue listindex