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