Получить индекс элемента по значению в списке redis
у меня есть список redis, который я создал, я использую его в качестве очереди в данный момент, который время от времени меняется. Моя проблема в том, что я хотел бы иметь возможность получить индекс элемента в этой очереди/списке по значению.
пример
Если у меня есть список со следующими значениями:
{"dan","eduardo","pedro"}
индексы будут:
0 : "dan"
1 : "eduardo"
2 : "pedro"
Я хочу иметь возможность, передавая значение, получить индекс этого значения на моем список.
Как "Эдуардо" и получить обратно "1".
возможно ли это, если да, то как бы вы это сделали?
также я должен сказать, что я выполняю команды очереди в свой список, удаляя элементы сверху и добавляя их внизу.
в настоящее время я использую node.js 0.6.6 и последний модуль redis с последней версией redis 2.4.4.
Я рад за решение только в redis-cli.
также нет ограничений другое, тогда это должно быть возможно сделать только с redis, без внешнего процесса и т. д. Однако, если вы хотите использовать команду EVAL с lua go для нее.
редактировать
также я думаю, что мой ответ может быть на отсортированных наборах, а не очередях.
5 ответов
Я не знаю подробностей клиента 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 для поиска индекса любого значения в списке. Команда O (N).
$ redis-cli --eval indexof.lua mylist , bar
(integer) 1
на bar
составила 1
> lindex mylist 1
"bar"
на nil
is -1
$ redis-cli --eval indexof.lua mylist , nil
(integer) -1
посмотреть http://redis.io/commands/eval дополнительные документы по команде ИВАЛ.
используйте сортированные наборы для реализации очереди.
добавить членов и использовать отметку времени в качестве оценки.
> ZADD queue 1326990501 foo 1326990502 bar 1326990503 baz 1326990504 qux
(integer) 4
вы можете вернуть членов в порядке FIFO и LIFO с помощью ZRANGE и ZREVRANGE соответственно.
ФИФО:
> ZRANGE queue 0 0
"foo"
ЛИФО:
> ZREVRANGE queue 0 0
"qux"
чтобы найти индекс члена, используйте ZRANK. ZRANK op - O (log (N))
> ZRANK queue bar
(integer) 1
как вы можете сказать сейчас, Redis не поддерживают такую операцию (грустное лицо).
хотя кто-то сделал некоторые довольно хорошие замечания о том, почему такая операция имела бы смысл, похоже, Сальваторе не будет реализован в ближайшее время.
есть в основном два обходных пути (как указано в других ответах):
- используйте пользовательский скрипт lua для поиска индекса в списке;
- используйте сортированный набор (вместо списка) с отметка времени как оценка и
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 ║
╚════════════════╩═══════════════════════╩══════════════════════╝
Да, это ошеломляющие 41 секунды всего для десяти тысяч элементов.
* В Windows 7, В Redis 2.8 (порт MSOpenTech), .NET 4 с включенной оптимизацией компилятора и StackExchange.Рэдис 1.0.488.
согласно билету 140 в списке вопросов redis.Ио
запрос функции: lRank
"привет, эта команда, скорее всего, не будет реализована, поскольку это и команда O(N), и та, которая обычно ощущается как необходимая, только когда есть некоторая ошибка в дизайне макета данных.- by Сальваторе Санфилиппо on https://github.com/antirez/redis/issues/140.
Я не совсем уверен, почему и как хотите узнать индекс элемент по значению может быть ошибкой в дизайне данных. Однако он дает понять, что вы можете использовать код lua и/или отсортированные наборы.
Так что up выстрел из него это нет возможности чтобы узнать индекс элемента в списке, кроме использование сценария lua.
однако в зависимости от реализации, т. е. дизайна данных, может быть лучше рассмотреть отсортированные наборы вместо списков.
используя сортированные наборы (ZADD и т. д.), Вы можете использовать ZRANK.
Edit: мой старый ответ ниже не работает, потому что ваш список изменяется, хотя это так, со списком, который растет только с помощью RPUSH.
вы можете сохранить индекс со значением (или его хэшем) в качестве ключа:
set listvalue listindex
чтобы сохранить ваш redis организованным, вы можете префикс этих ключей с именем списка:
set listname:listvalue listindex