Reputation: 43
I have need to call Redis HMSET with a Redis Lua script. Here is a coffee script:
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
What is the correct syntax / pattern to call HMSET in the LUA script? BTW - I am aware of the redis.HMSET command.
Upvotes: 1
Views: 2700
Reputation: 7020
First, are you sure you are using eval
in your CoffeeScript Redis library correctly? You are apparently passing three arguments: the script, the number of keys and an array. I suspect this is not how it works. If this is node_redis, either everything or nothing must be in the array, so try:
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
(There is probably a nicer syntax but I don't know CoffeeScript.)
Secondly, in this example you are trying to HMSET a single field/value pair:
HMSET lua_script 1111-1114 id 111
Actually you could replace HMSET by HSET here, but let's make it work first.
In this line:
local res = redis.call('hmset', KEYS[1], ARGV[1])
You are only calling HMSET with two arguments, the key containing the hash and the field. You need to add the value which is the second argument:
local res = redis.call('hmset', KEYS[1], ARGV[1], ARGV[2])
This will make your example work, but what if you want to actually set multiple fields (which is the goal of MHSET) like so?
HMSET lua_script 1111-1114 id 111 id2 222
In CoffeeScript you would write:
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
... but now you have four elements in ARGV
to pass to redis.call
in Lua. Actually you have to pass all the elements of ARGV
, and this is called unpack() in Lua:
local res = redis.call('hmset', KEYS[1], unpack(ARGV))
The only issue with using unpack()
is that if you have a real lot of elements in ARGV
(thousands) it can break because it will overflow the stack, in which case you should use a loop in the Lua script to call HMSET on slices of ARGV
, but you should probably not worry about that for now...
Upvotes: 1