我希望能够存储"商店x的数据在星期一上午9点到下午5点之间开放,但它只在星期六上午9点和下午12点开放,并且#34;
使用redis存储此内容的最佳方法是什么?
我后来想用这样的东西来查询它。告诉我所有在周六上午10:30开放的商店
答案 0 :(得分:1)
在Redis中,与大多数其他NoSQL数据库一样,您希望以最适合回答查询的方式存储数据。您可以通过多种方式表示此数据并回答查询,在它们之间进行选择需要了解您需要支持的其他访问模式。
但是,仅在这个特定问题的上下文中,执行该IMO的最简单方法是每周使用两个排序集。假设商店连续开放,每天最多一次(即没有午休),这些分类集的成员应该是商店ID,而分数是他们的开放时间 - 第一个排序集的分数将表示时间商店打开,而第二个商店关闭。例如:
ZADD monday:open 9 store:x
ZADD monday:close 17 store:x
ZADD saturday:open 9 store:x
ZADD saturday:close 12 store:x
准备好所有排序集后,回答查询需要两次调用ZRANGEBYSCORE
并将结果相交。下面的代码片段演示了如何使用Lua进行操作,因为在大多数情况下,使用服务器脚本比将整个内容移动到客户端更有效。
注意:在Lua中进行交叉的另一种方法实际上是将临时结果存储在Redis'设置并调用SINTER
。
-- helper function to make a "set" out of a table
local function makeset(t)
local r = {}
for _, v in ipairs(t) do r[v] = true end
return(r)
end
-- get opening and closing hours for a given day
local ot = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1])
local ct = redis.call('ZRANGEBYSCORE', KEYS[2], '(' .. ARGV[1], '+inf')
-- convert to sets and choose the smaller set as s1
local s1 = {}
local s2 = {}
if #ot < #ct then
s1 = makeset(ot)
s2 = makeset(ct)
else
s1 = makeset(ct)
s2 = makeset(ot)
end
-- intersect s1 and s2
local t = {}
for k in pairs(s1) do
t[k] = s2[k]
end
-- prepare a response table
local r = {}
for k in pairs(t) do
r[#r+1] = k
end
return(r)
运行此脚本,将两个键和小时传递给它,如下所示:
redis-cli --eval storehours.lua saturday:open saturday:close , 10.5