我需要用redis lua脚本调用redis hmset。这是咖啡剧本:

redis = require("redis")
client = redis.createClient();

lua_script = "\n
-- here is the problem\n
local res = redis.call('hmset', KEYS[1],ARGV[1])\n
print (res)\n
-- create secondary indexes\n
--\n
--\n
return 'Success'\n
"

client.on 'ready', () ->
  console.log 'Redis is ready'
  client.flushall()
  client.send_command("script", ["flush"])

  args = new Array(3)

  args[0] = '1111-1114'
  args[1] = 'id'
  args[2] = '111'
  callback = null
  #client.send_command("hmset", args, callback) # this works

  client.eval lua_script, 1, args, (err, res) ->
    console.log 'Result: ' + res

在lua脚本中调用hmset的正确语法/模式是什么?
顺便说一下-我知道redis.hmset命令。

最佳答案

首先,您确定在您的coffeescript redis库中正确使用了eval吗?显然,您传递了三个参数:脚本、键数和数组。我怀疑这不是它的工作原理。如果这是node_redis,则数组中必须包含所有内容或不包含任何内容,因此请尝试:

args = new Array(5)

args[0] = lua_script
args[1] = 1
args[2] = '1111-1114'
args[3] = 'id'
args[4] = '111'
callback = null

client.eval args, (err, res) ->
  console.log 'Result: ' + res

(可能有更好的语法,但我不知道coffeescript。)
其次,在本例中,您试图hmset单个字段/值对:
HMSET lua_script 1111-1114 id 111

实际上,您可以在这里用hset替换hmset,但我们先让它工作。
在这一行中:
local res = redis.call('hmset', KEYS[1], ARGV[1])

您只使用两个参数调用hmset,即包含哈希值的键和字段。您需要添加作为第二个参数的值:
local res = redis.call('hmset', KEYS[1], ARGV[1], ARGV[2])

这将使您的示例起作用,但是如果您真的想这样设置多个字段(这是mhset的目标)呢?
HMSET lua_script 1111-1114 id 111 id2 222

在coffeescript中,您可以编写:
args = new Array(7)

args[0] = lua_script
args[1] = 1
args[2] = '1111-1114'
args[3] = 'id'
args[4] = '111'
args[5] = 'id2'
args[6] = '222'
callback = null

client.eval args, (err, res) ->
  console.log 'Result: ' + res

…但现在在ARGV中有四个元素要传递到lua中的redis.call。实际上,您必须传递ARGV的所有元素,这在lua中称为unpack()
local res = redis.call('hmset', KEYS[1], unpack(ARGV))

使用unpack()的唯一问题是,如果您在ARGV(数千)中有很多元素,它可能会中断,因为它会溢出堆栈,在这种情况下,您应该在lua脚本中使用循环来调用ARGV的切片上的hmset,但您现在可能不应该担心这个问题……

07-27 20:12