【问题标题】:Lua booleans don't have expected behavior in redisLua布尔值在redis中没有预期的行为
【发布时间】:2013-06-06 12:07:22
【问题描述】:

我有一个脚本

local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
local retval = {};
for i, field in pairs(fields) do
    if((string.match(tostring(field),'ev')) ~= nil) then
        retval[i] = {field, (string.match(tostring(field),'ev') ~= nil) }
    end
end
return retval

此脚本返回一个空列表

当我将 if 语句更改为看起来像时

if((string.match(tostring(field),'.')) ~= nil) then
    ...

我得到了一个长长的列表,其中包括以下内容

...
...
60) 1) "applet:1:metric:viewelement:20130607"
    2) (nil)
61) 1) "applet:1:total_events:20130529"
    2) (integer) 1
...
...

如果我用

替换 if 语句
if(1)

我得到相同的长键列表

我也尝试过使用string.find,它也有类似的行为。

似乎是一个模式的唯一一点是,如果匹配的字符串在字符串中出现多次,或者如果它出现在开头,则if 语句将通过。我不能确定这一点,但它可能会有所帮助。

我正在使用以下命令运行此脚本

$ redis-cli eval "$(cat get_keys.lua)" 0

【问题讨论】:

    标签: string lua redis match string-matching


    【解决方案1】:
    1. 你不需要做if((string.match(tostring(field),'ev')) ~= nil)。你可以做if(string.match(tostring(field),'ev'))
    2. 脚本失败的原因是 lua 不支持表中的 nil 键。如果您设置some_table[1]some_table[2]some_table[5],然后返回数组,它看起来会以some_table[2] 结尾。由于您仅在 if 语句通过时设置数组,如果它在 retval[1] 上失败,则不会返回数组的其余部分。

    简单的解决方法是:

    local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
    local retval = {};
    for i, field in pairs(fields) do
        if(string.match(tostring(field),'ev')) then
            retval[i] = {field, (string.match(tostring(field),'ev') ~= nil) }
        else retval[i] = 'some_nil_value'
        end
    end
    return retval
    

    我想你也可以使用table default values,但我还没有玩过,所以这里不能提供太多信息。

    [EDIT] OP 表示他不想要 nil 占位符。在这种情况下,可以使用以下内容:

    local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
    local retval = {};
    for i, field in pairs(fields) do
        if(string.match(tostring(field),'ev')) then
            retval[#retval+1] = {field, (string.match(tostring(field),'ev') ~= nil) }
        end
    end
    return retval
    

    【讨论】:

    • 是的。脚本中有一些来自调试的额外内容。这可行,但不是最佳的
    • @PeterKlipfel 在哪些方面不是最佳的?使用默认表可能会提高一点性能,但我怀疑它会对基准测试产生任何影响。
    • 我的意思是我的回答。我应该指定它不是我的用例的最佳选择,其中包括解析放入数组中的 nil 值。我确信我的解决方案可以美化,但它使用的内存更少
    • 您的原始解决方案有一个与您的 hkeys 调用的确切大小相同的数组,该数组使用 nil 占位符返回。如果你想避免使用 nil 占位符,你为什么首先问这个问题?无论如何,如果你想要的话,我会用一种更简洁的方式来修改我的答案以避免占位符。
    • 抱歉,我不是故意要听起来像个朋克。我提出我的答案是因为如果有人遇到这个答案,问题可能会帮助调试。它具有返回较小列表的好处。我不知道为什么我没有拿回我的清单
    【解决方案2】:

    Eli 的回答很有效,但我认为原因是 Lua 中处理列表的方式存在一个微妙的问题。我想解释一下我的想法。

    所以,作为测试,我在retval 中插入了一个额外的字段,偶尔它是零。我注意到在这些调用中,列表的其余部分没有返回。

    我认为幕后发生的事情是 redis 正在处理整个列表,但是当它返回时,它在第一个 nil 处被截断。所以有时有一个列表,有时没有。作为一个黑客,我将脚本重写为

    local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
    local retval = {};
    local i = 0
    for j, field in pairs(fields) do
        if string.find(field,"ev") then
            retval[i] = {field, string.match(field,'ev') }
            i = i+1;
        end
    end
    return retval
    

    它成功了!

    所以 Eli 的答案有效,因为 retval 没有被截断。但是,当您需要解析返回的列表时,它会占用更多的带宽和 cpu 时间

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-29
      • 2013-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2015-10-24
      相关资源
      最近更新 更多