Redis - 为什么 Lua 表作为返回值时不起作用

15

当我把这段代码通过Redis EVAL运行时,它没有返回任何结果。你知道为什么会出现这种情况吗?

redis-cli EVAL "$(cat bug.lua)" 0

bug.lua

local retv = {}
retv["test"] = 1000

return retv

如果我初始化表格,那么只有这个值会被打印出来。

$ cat bug.lua 
--!/usr/bin/env lua


local retv = {"This", "is", "a", "bug" }
retv["test"] = 1000

return retv

$ redis-cli EVAL "$(cat bug.lua)" 2 a b
1) "This"
2) "is"
3) "a"
4) "bug"

你的实际命令在 0 前面有闭合引号吗?如果没有,它将无法正常工作。我想知道这是打字错误还是真的。 - Oliver
是的,你说得对。这只是一个打字错误。我在命令行上已经弄对了。正在修正问题。感谢你指出来。 - vivekv
如果 bug.lua 有 local msg = "hi"; return msg,它能正常工作吗?如果你 cat 一个不存在的文件,会得到错误消息吗?你正在返回对表的引用,而不是表的字符串表示形式,Redis 知道如何显示引用(实质上是指针)吗? - Oliver
Lua解释器运行良好,文件也能够正常加载。已经进行了检查。 - vivekv
关于表引用的返回,Redis手册(http://redis.io/commands/eval)指出Lua表会被转换为适当的Redis数据结构。因此我不确定是否存在问题。 - vivekv
有趣的是,我对初始化表格进行了小改动,现在它可以正常工作了。已经更新了问题并附上了更改后的脚本。 - vivekv
2个回答

22

如果您查看Redis EVAL文档,您可以了解Redis用于将Lua表转换为Redis回复所使用的规则:

  1. Lua表(数组)-> Redis多个批量回复(如果有任何在Lua数组中的第一个nil被截断
  2. 具有单个ok字段的Lua表 - > Redis状态回复
  3. 具有单个err字段的Lua表 - > Redis错误回复

因此,除了特殊情况2和3外,Redis假定您的表是序列(即列表),这意味着它会读取retv[1]、retv[2]、...,直到遇到一个nil元素(这里是相应的源代码部分)。

这就解释了为什么在您的情况下忽略了retv["test"]

如果您将代码更改为:

local retv = {"This", "is", "a", "bug" }
retv[5] = 1000
return retv

接着会返回这个额外的元素:

1) "This"
2) "is"
3) "a"
4) "bug"
5) (integer) 1000

就是这样。 Redis不支持Lua的任意表格。我不知道!非常感谢。 - vivekv
是的!这是因为它需要将Lua返回值转换为有效的Redis协议(又名RESP)数据类型,即简单字符串、错误、整数、块字符串和数组 - 并且没有关联数组。 - deltheil
非常感谢。这对我帮助很大!同时,deltheil写了重要的句子“...没有关联数组”,这帮助我找出问题所在! - psulek

11

来自@deltheil的回答是有效的。

不过请记住,您可以使用cjson库将表打包并传递给消费者。

您的lua文件:

local retv = {"This", "is", "a", "bug" }
retv["test"] = 1000

return cjson.encode(retv)

命令:

redis-cli EVAL "$(cat bug.lua)" 0

结果:

"{\"1\":\"This\",\"2\":\"is\",\"3\":\"a\",\"4\":\"bug\",\"test\":1000}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接