在redis列表中,通过值获取一个项的索引。

我创建了一个 redis 列表,目前将其用作队列,有时会反转。我的问题是,我想通过值获取队列/列表中项的索引。

示例

如果我有一个值如下的列表:

{"dan","eduardo","pedro"}

索引将是:

0 : "dan"
1 : "eduardo"
2 : "pedro"

我想通过传递值来获得该值在我的列表中的索引。

像 "eduardo",返回 '1'。

如果可能的话,应该如何实现?

还有一件事我应该说的是,我正在向我的列表执行队列命令,从顶部删除项并将它们添加到底部。

我目前正在使用 node.js 0.6.6 和最新的 redis 模块以及最新的 redis 版本 2.4.4。

如果您希望仅在 redis-cli 中使用,则可以提供解决方案。

另外,没有任何限制,只要可能性仅在 redis 中完成,不使用外部进程等,但是如果您想使用 lua 的 EVAL 命令,请使用它。

编辑

另外,我认为我的答案可能在排序集上,而不在队列上。

原文链接 https://stackoverflow.com/questions/8899111

点赞
stackoverflow用户1152077
stackoverflow用户1152077

使用排序集合(ZADD等)可以使用ZRANK

编辑:我的旧答案不起作用,因为你的列表会发生变化,尽管只有使用RPUSH增长的列表。

您可以将索引与值(或其哈希)一起存储为键:

set listvalue listindex

为了保持您的Redis组织有序,您可以在这些键前缀中加上列表名称:

set listname:listvalue listindex
2012-01-18 09:07:13
stackoverflow用户230264
stackoverflow用户230264

我不知道关于 nodejs 客户端的细节,但以下是使用 lua 实现的一个非常简单的 indexOf 命令。

在我的 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 的索引为 -1。

$ redis-cli --eval indexof.lua mylist , nil
(integer) -1

请查看 http://redis.io/commands/eval 中关于 EVAL 命令的更多文档。

2012-01-19 11:44:01
stackoverflow用户230264
stackoverflow用户230264

使用有序集合来实现队列。

添加成员并将时间戳用作得分。

> ZADD queue 1326990501 foo 1326990502 bar 1326990503 baz 1326990504 qux
(integer) 4

您可以通过使用 ZRANGE(FIFO) 和 ZREVRANGE(LIFO) 返回成员。

FIFO:

> ZRANGE queue 0 0
"foo"

LIFO:

> ZREVRANGE queue 0 0
"qux"

要查找成员的索引,请使用 ZRANK。 ZRANK 操作的时间是 O(log(N))

> ZRANK queue bar
(integer) 1
2012-01-19 15:40:57
stackoverflow用户176478
stackoverflow用户176478

按照redis.io的问题列表上的第140个票据

功能需求:lRank

"嗨,这个命令可能不会被实现,因为它是一个 O(N) 命令,通常只有在数据布局设计存在一些错误时才感觉需要。" 由 Salvatore Sanfilippohttps://github.com/antirez/redis/issues/140 上说。

我不太确定为什么想要按值查找项目的索引可能会是数据设计中的错误。 然而,他明确指出,你可以使用Lua代码和/或排序集合。

因此,它的核心是,没有其他方法来查找列表中项的索引,除非使用Lua脚本

然而,根据实现,即数据设计,考虑使用排序集合可能会更好。

2012-01-24 23:32:32
stackoverflow用户1316620
stackoverflow用户1316620

由现在开始,您可以通过 Redis 不支持此操作(伤心的脸)看出来。

虽然某人对为什么这样的操作有意义发表了一些不错的 评论,但看起来 Salvatore 不会很快实现它。

基本上有两种解决方法(如其他答案所指出的):

  • 使用自定义 lua 脚本找到列表中的索引;
  • 使用排序集合(而不是列表)以时间戳为分数和 ZRANK 为索引。

由于第一个是 O(N),而后者仅是 O(log(N)),因此您可以知道哪个表现更好。

无论如何,我决定 测试一下*:

╔════════════════╦══════════════════════╦══════════════════════╗
â•‘                â•‘ 带有 ZRANK 的排序集合 â•‘ 使用 lua 脚本的列表 â•‘
╠════════════════╬══════════════════════╬══════════════════════╣
â•‘ 1000 个元素 â•‘  0.0638264    â•‘  0.2723238   â•‘
╠════════════════╬═══════════════════════╬═════════════════════╣
â•‘ 10000 个元素 â•‘ 00.4484714   â•‘  41.0661683   â•‘
╚════════════════╩══════════════════════╩══════════════════════╝

是的,仅有一万个元素需要长达 41 秒的时间。

\* 在 Windows 7 上,使用 Redis 2.8(MSOpenTech 端口),.NET 4 和启用编译器优化以及 StackExchange.Redis 1.0.488。

2015-11-18 21:17:56
stackoverflow用户3322356
stackoverflow用户3322356

使用 LPOS 命令(从 Redis 版本 6.0.6 开始可用)可以获取 redis 列表中元素的索引。

文档中获取:

  • 命令 - LPOS key element [FIRST rank] [COUNT num-matches] [MAXLEN len]
  • 该命令返回 Redis 列表中匹配元素的索引。
  • 默认情况下,当没有给出选项时,它将从头到尾扫描列表,查找“element”的第一个匹配。如果找到元素,则返回其索引(列表中基于零的位置)。否则,如果找不到匹配项,就返回 NULL。

因此,在您的情况下,列表 {"dan","eduardo","pedro"} 的键为 users

LPOS users eduardo

必须返回 1。我个人还没有尝试在 lua 脚本中使用它,因此没有提供脚本,但我认为应该很简单。

2020-06-19 17:26:18