8

How can we use lua scripting to implement multi-get.

Let's say if I've set name_last to Beckham and name_first to David. What should the lua script be in order to get both name_last and name_first in one go?

I can implement something like:

eval "return redis.call('get',KEYS[1])" 1 foo

to get the value of single key. Just wondering on how to enhance that scripting part to get values related to all keys (or multiple keys) by just making one call to redis server.

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
user_ab
  • 225
  • 1
  • 3
  • 6

2 Answers2

6

First, you want to send the fields you want to return to EVAL (the 0 indicates that there are no KEYS so these arguments will be accessible from ARGV):

eval "..." 0 name_last name_first

Second, you can query the values for the individual fields using MGET:

local values = redis.call('MGET', unpack(ARGV))

Third, you can maps the values back to the field names (the index of each value corresponds to the same field):

local results = {}
for i, key in ipairs(ARGV) do
  results[key] = values[i]
end
return results

The command you'll end up executing would be:

eval "local values = redis.call('MGET', unpack(ARGV)); local results = {}; for i, key in ipairs(ARGV) do results[key] = values[i] end; return results" 0 name_last name_first
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
  • though MGET solves the purpose, I'm just wondering if LUA scripting has any role to play in this scenario. From the readings that I've done online, my understanding is that LUA scripting actually is a good approach(a step forward from pipelining) where we can minimize the calls to redis server. – user_ab Feb 26 '15 at 17:34
  • @user_ab I seem to have misunderstood your original question. Basically, you want to do `eval "Return values of name_last and name_first"`and get back `{name_last = "Beckham", name_first = "David"}`? – Uyghur Lives Matter Feb 26 '15 at 18:14
  • Thank you very much. I appreciate you for sharing your knowledge. Your suggestions and answers would definitely help me delve deeper into redis. – user_ab Feb 27 '15 at 04:40
  • 1
    @user_ab Lua helps when you implement stuff that Redis doesn't do with its standard commands API. In this case, Lua will **not be better** than `MGET`, unless you want to do something server-side before returning the values. Otherwise, don't use eval from your code, just call your Redis client's MGET. – Itamar Haber Feb 27 '15 at 17:06
  • 1
    @Itamar Haber, ah...got it. With your suggestion, I'm now bit clear about the application of scripting in redis. Thank you. – user_ab Feb 28 '15 at 15:15
4

Do a loop over the KEYS table and for each store its GET response in a take that you return. Untested code:

local t = {}
for _, k in pairs(KEYS) do
  t[#t+1] = redis.call('GET', k)
end
return t

P.S. You can also use MGET instead btw :)

Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
  • 2
    let's say we have 10 keys. Per your suggestion, aren't we making 10 separate calls to redis server to get value at each key? I just wanted to make one call to redis server and get all those values for 10 keys. – user_ab Feb 26 '15 at 14:25
  • Lua arrays are declared with {}, like: local t = { } – xyz Sep 19 '18 at 00:23
  • 1
    @xyz Totally correct - fixed, thanks! (I did write it was untested ;)) – Itamar Haber Sep 19 '18 at 00:47