In Azure Redis Enterprise with TimeSeries module enabled I have the following time series with 4 values of 1 at the key "key1":
$ TS.RANGE key1 - +
1) 1) (integer) 1693381431951
2) 1
2) 1) (integer) 1693381435201
2) 1
3) 1) (integer) 1693381436720
2) 1
4) 1) (integer) 1693381438037
2) 1
I am able to retrieve the same results by a Lua script:
$ EVAL "return redis.call('TS.RANGE', KEYS[1], '-', '+')" 1 key1
1) 1) (integer) 1693381431951
2) 1
2) 1) (integer) 1693381435201
2) 1
3) 1) (integer) 1693381436720
2) 1
4) 1) (integer) 1693381438037
2) 1
My question is how to sum up the values (and to get a 4 as result in the shown case)?
I am trying the following Lua code:
$ EVAL "local sum = 0; for stamp, val in redis.call('TS.RANGE', KEYS[1], '-', '+') do sum = sum + val end; return sum" 1 key1
(error) ERR Error running script (call to f_28243bc2b451f1770c76c1d7fcce23e7285f3baa): @user_script:1: user_script:1: attempt to call a table value
Doesn't TS.RANGE return pairs of timestamp and numeric values?
My background is that I am calling ScriptEvaluateAsync()
in my C# application and would like to sum up all values in a time series, when given a key.
This can get a bit messy and the Redis Lua debugger can help (https://redis.io/docs/interact/programmability/lua-debugging/).
Here's a solution that will do what you need but the Lua could possibly be optimized - I'm not a Lua expert :)
local sum = 0;
local rangeResponse = redis.call('ts.range', KEYS[1], '-', '+')
for _, item in pairs(rangeResponse) do
local val = tonumber(item[2]["ok"])
sum = sum + val
end
return sum
This unpacks the TS.RANGE
response and sums the values. Let's set up some data to use it:
127.0.0.1:6379> 4 ts.add key1 * 1
(integer) 1693393058028
(integer) 1693393058034
(integer) 1693393058035
(integer) 1693393058036
and check what we have:
127.0.0.1:6379> TS.RANGE key1 - +
1) 1) (integer) 1693393058028
2) 1
2) 1) (integer) 1693393058034
2) 1
3) 1) (integer) 1693393058035
2) 1
4) 1) (integer) 1693393058036
2) 1
Now let's store the script in the redis server (I've put the script in a file called sumts.lua
:
$ redis-cli -x script load < ~/Desktop/sumts.lua
"caf0749de1e79a8955e212a2fb0ea34e6c76a28c"
We get the SHA for the script back and can use that to call it:
127.0.0.1:6379> evalsha caf0749de1e79a8955e212a2fb0ea34e6c76a28c 1 key1
(integer) 4
we get the integer response 4, the sum of the values in the time series.
Here's an example of how to run through this script in the Lua debugger and see local variables:
$ redis-cli --ldb --eval ~/Desktop/sumts.lua key1
then...
Lua debugging session started, please use:
quit -- End the session.
restart -- Restart the script in debug mode again.
help -- Show Lua script debugging commands.
* Stopped at 1, stop reason = step over
-> 1 local sum = 0;
lua debugger> n
* Stopped at 2, stop reason = step over
-> 2 local rangeResponse = redis.call('ts.range', KEYS[1], '-', '+')
lua debugger> n
<redis> ts.range key1 - +
<reply> [[1693393058028,"+1"],[1693393058034,"+1"],[1693393058035,"+1"],[1693393058036,"+1"]]
* Stopped at 3, stop reason = step over
-> 3 for _, item in pairs(rangeResponse) do
lua debugger> n
* Stopped at 4, stop reason = step over
-> 4 local val = tonumber(item[2]["ok"])
lua debugger> n
* Stopped at 5, stop reason = step over
-> 5 sum = sum + val
lua debugger> print
<value> sum = 0
<value> rangeResponse = {{1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}}
<value> (for generator) = "function@0x562d34cb1590"
<value> (for state) = {{1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}; {1.69339e+12; {["ok"]="1"}}}
<value> (for control) = 1
<value> _ = 1
<value> item = {1.69339e+12; {["ok"]="1"}}
<value> val = 1
You can keep using n
to step through the loop.
Hope this helps.