如何使用Redis表示此数据?

时间:2015-06-22 17:06:30

标签: redis

我希望能够存储"商店x的数据在星期一上午9点​​到下午5点之间开放,但它只在星期六上午9点和下午12点开放,并且#34;

使用redis存储此内容的最佳方法是什么?

我后来想用这样的东西来查询它。告诉我所有在周六上午10:30开放的商店

1 个答案:

答案 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