Получить индекс элемента по значению в списке 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