【问题标题】:how to delete key from list in redis matching a pattern?如何从匹配模式的redis列表中删除键?
【发布时间】:2015-08-17 10:42:59
【问题描述】:

使用 ruby​​ redis 客户端

我有一个键,其中包含一个值列表,它们遵循

的模式
campaign_id|telephone|query_id

在一个单独的列表中有数千个,我想要做的是从该 redis 列表中删除所有具有例如 query_id 为 4 的列表。你能通过某种模式匹配来做到这一点吗?请有人给我一个例子,因为我一直在阅读其他问题并且有点迷茫

【问题讨论】:

  • list.reject { |e| e =~ /|#{query_id}$/ }
  • 我的意思是实际上从redis中删除它们而不是从返回的内容中拒绝它们

标签: ruby-on-rails ruby regex redis


【解决方案1】:

您基本上有以下两种选择之一:a) 在您的 (RoR) 应用程序中执行或 b) 在 Redis 中执行。

我不是 RoR 专家,因此我无法就如何操作提供建议,但请注意,采用 a) 路径,您基本上会将整个列表移动到您的应用程序并在那里进行过滤。您的列表越大,跨网络所需的时间就越长。

选项 b) 意味着您将在 Redis 中过滤列表 - 当您使用 Lua 时,这可以简单而有效地完成。示例:

$ cat dellistbyqueryid.lua
-- removes a range of list elements that confirm to a given
-- query_id. Elements are stored as: 'campaign_id|telephone|query_id'
-- KEYS[1] - a list
-- ARGV[1] - a query_id
-- return: number of elements removed

local l = tonumber(redis.call('LLEN', KEYS[1]))
local n = 0

while l > 0 do
  local curr = redis.call('LINDEX', KEYS[1], -1)
  local id = curr:match( '.*|.*|(.*)' )
  if id == ARGV[1] then
    redis.call('RPOP', KEYS[1])
    n = n + 1
  else
    redis.call('RPOPLPUSH', KEYS[1], KEYS[1])
  end
  l = l - 1
end

return n

输出:

$ redis-cli LPUSH list "foo|bar|1" "baz|qaz|2" "lua|redis|1"
(integer) 3
$ redis-cli --eval dellistbyqueryid.lua list , 1
(integer) 2
$ redis-cli LRANGE list 0 -1
1) "baz|qaz|2"

【讨论】:

  • 但实际删除部分在哪里?我猜作者询问了从列表中删除值而不是过滤输出的问题。关于案例a)这种情况基本上意味着过滤RoR中的所有列表,然后将现有列表与过滤后的列表交换?因为 LREM 不支持通过正则表达式删除也不支持按索引删除。
  • @RuslanN 您实际上非常非常非常正确。立即编辑。