0
votes

I'm trying to write an extremely simple Lua script to access the hyperloglog functionality in redis from node_redis. I have 1 key and multiple hashes as elements to pass. I can successfully do this only if I hard code the key and argument as in the following:

script: 'return redis.call("pfadd", 'testkey', 'valvalval')'

While this works perfectly, this is not very useful...

I've tried every possible way I can think of to access KEYS and ARGV arrays and this is what I currently have in my .js file:

var script = '\
local val = 0 \
for _, hash in pairs(ARGV) do \
     redis.call("pfadd", KEYS[1], hash) \
end \
return val';

And to call my script:

redisInstance.eval(script, 1, args, function (ret) {
    console.log(ret);
});

args is an array as follows:

['key','hash1','hash2','hash3', ...,'hash30']

The callback is always null and no keys are set on the server... The KEYS and ARGV arrays are not accessed... (when hardcoded as I said, it works fine..)

I need to pass all of the hashes as elements (total of about 30 each time) and receive the integer replies.

Thanks in advance for the help.

2
what is '1' for? in redisInstance.eval(script, 1, args, function (ret) {...} ? - zenbeni
A couple quick things that jump out: the callback takes two params, error and result, not just the result. Also, try invoking it like this: redisInstance.eval([script, 1, ['key'], ['hash1', 'hash2']], function(error, resp){ ... }) - aembke
The 1 specifies the number of keys. - user3311886

2 Answers

0
votes

The previous answer was wrong, you need to concat all arguments and values to single array(sample using lodash):

var keys = _.keys(filteredData);
var values = _.values(filteredData); 
var command = ["function code",keys.length];
command = command.concat(keys,values);

Anyhow you should consider the ioredis as it supports abstraction for lua scirpts.

-1
votes

I'm answering my own question which is aembke's comment... Thanks for the help aembke!

var script =  
'\
local val = 0 \
for _,hash in pairs(ARGV) do \
  val = tonumber(redis.call("pfadd", KEYS[1], hash)) \
end \
return val';

call eval:

redisInstance.eval(args, function(err, res){
    //use res
})

args array:

[script, "#keys" ("1" in this case), ['key string'], ['hash1', ...., 'hash30']]