Lua script for Redis which sums the values of keys
EVAL
requires a minimum of two arguments; the script and the number of keys you are passing to the script. In this case, you are passing zero keys, meaning the script can be invoked as follows:redis-cli EVAL "$(cat sum.lua)" 0
or:
redis-cli --eval sum.lua
Your loop structure for iterating over the values returned from
KEYS
was incorrect; I have fixed it for you.You need to convert the value returned from
GET
from a string to a number using Lua'stonumber
function.
With the above changes made, the following script should work for you:
local sum = 0
local matches = redis.call('KEYS', 'carlos:*')
for _,key in ipairs(matches) do
local val = redis.call('GET', key)
sum = sum + tonumber(val)
end
return sum
Some important points for starters:
KEYS and ARGV : These are tables in Lua which are going to hold the data sent by your redis client inside Lua Script in Redis.
Tables are associative arrays, and Lua’s only mechanism for structuring data. You can think of them as the equivalent of an array in whatever language you’re most comfortable with.Tables are one-based, that is, indexing starts at 1. So the first element in
mytable
ismytable[1]
, the second ismytable[2]
, etc.Tables cannot hold nil values. If an operation would yield a table of
[ 1, nil, 3, 4 ]
, the result will instead be[ 1 ]
— the table is truncated at the first nil value.
Note : When writing Lua scripts for Redis, every key that is accessed should be accessed only by the KEYS table. The ARGV table is used for parameter-passing
I think you can now transfer keys and args from whatever language to your Lua script.
Now we can proceed to Lua's redis call to redis command KEYS.
To iterate over the returned data you have option of lua's pairs
and ipairs
and some quick difference can be spotted here. For above case ipairs will be fine.
Now we can proceed to data type issue.
Lua and Redis have different type systems, so it’s important to understand how values may change when crossing the Redis-Lua border. When a number comes from Lua back to a Redis client, it becomes an integer — any digits past the decimal point are dropped:
local indiana_pi = 3.2
return indiana_pi
When you run this script, Redis will return an integer of 3 — you lose the interesting pieces of pi. Seems simple enough, but things get a bit more tricky when you start interacting with Redis in the middle of the script. An example:
local indiana_pi = 3.2
redis.call("SET", "pi", indiana_pi)
return redis.call("GET", "pi")
The resulting value here is a string: "3.2" Why? Redis doesn’t have a dedicated numeric type. When we first SET
the value, Redis saves it as a string, losing all record of the fact that Lua initially thought of the value as a float
. When we pull the value out later, it’s still a string.
Values in Redis that are accessed with GET/SET
should be thought of as strings except when numeric operations like INCR
and DECR
are run against them. These special numeric operations will actually return integer replies (and manipulate the stored value according to mathematical rules), but the “type” of the value stored in Redis is still a string value.
Above answer is taken from this awesome blog post on:
https://www.redisgreen.net/blog/intro-to-lua-for-redis-programmers/