I have data in the form of a tuple (S, T), where S is string and T is integer. Neither S nor T is unique, while their combination is unique. I need to get all tuples where S1 == S2
and |T1 - T2| <= C
. Is is possible to do efficiently with Redis?
Asked
Active
Viewed 461 times
2
-
I think your question would benefit if you clarify whether the tuples in the dataset are unique. Regardless, because of the 64-bit requirement I believe it would be hard to pull it off (hard as in inefficient) - Redis doesn't have a native integer data type and the biggest integer it can handle is about 53 bits (scores in a Sorted Set are doubles). – Itamar Haber May 04 '16 at 00:55
-
I relaxed question conditions a bit, but are there some other options(another database) which would fit better in this task? – assp1r1n3 May 04 '16 at 07:15
1 Answers
1
One way would be to store the data in a list and do the retrieval with a Lua script. First, for tuples of the form (Sn,Tn)
, insert it like this:
LPUSH myKey S1:T1
LPUSH myKey S2:T2
... and so on
Then, use the Lua script below:
local function split(div,str)
if (div=='') then return false end
local pos,arr = 0,{}
for st,sp in function() return string.find(str,div,pos,true) end do
table.insert(arr,string.sub(str,pos,st-1))
pos = sp + 1
end
table.insert(arr,string.sub(str,pos))
return arr
end
local key = KEYS[1]
local sVal = ARGV[1]
local tVal = tonumber(ARGV[2])
local cVal = tonumber(ARGV[3])
local length = redis.call("LLEN", key)
if (tonumber(length) == 0) then
return nil
end
local data = redis.call("LRANGE", key, 0, tonumber(length))
local retval = {}
for index,val in pairs(data) do
local parts = split(":", val)
if (parts[1] == sVal and math.abs(tonumber(parts[2]) - tVal) <= cVal) then
table.insert(retval, val)
end
end
return retval
Save it as script.lua
and execute it with:
$ redis-cli "$(cat script.lua)" 1 myKey sValue tValue cValue
This will return all tuples (in Sn:Tn
form) that matches S1 == S2 and |T1 - T2| <= C
.

Duru Can Celasun
- 1,621
- 1
- 16
- 28
-
-
Assuming you mean time complexity, it would be `O(n)` since it has to iterate the entire list. I don't think you could do better than `O(n)` with Redis' data structures, but I'd love to be proven wrong on that :) – Duru Can Celasun May 04 '16 at 10:30