我有一个看起来像这样的集合(除了它有大约8000个项目):
{"id":563244,"stock_id":693,"value":"9.17","span_minutes":1440,"symbol":"BCS"}
{"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
{"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
{"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
现在,我要输入的内容是:
值介于20和100之间
span_minutes在5000到8000之间
我可以通过首先创建2个新的排序集,然后使用zrangebyscore
提取我想要的条目来获得这些信息:
ZADD values 9.17 '{"id":563244,"stock_id":693,"value":"9.17","symbol":"BCS"}'
ZADD values 21.09 {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
ZADD values 91.52 {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
ZADD values 127.60 {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
ZADD spans 1440 '{"id":563244,"stock_id":693,"value":"9.17","symbol":"BCS"}'
ZADD spans 2880 {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
ZADD spans 7200 {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
ZADD spans 5760 {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
现在,如果我要过滤这些集合以获得所需的值,则可以执行以下操作:
$value_range = Redis::zrangebyscore('values',20,100);
$span_range = Redis::zrangebyscore('spans',5000,8000);
分别返回:
1) {"id":565527,"stock_id":10093,"value":"21.09","span_minutes":2880,"symbol":"GDXS"}
2) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
和
1) {"id":565269,"stock_id":8883,"value":"127.60","span_minutes":5760,"symbol":"SAA"}
2) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
现在我需要的是一种将这两套组合的方法。从Redis文档中可以看到,我应该能够为此目的使用zinterstore,但是我不理解语法,无论如何我都会尝试抛出错误或返回整数0。例如:
Redis::zinterstore('intersection', 2, $value_range, $span_range);
返回错误。
$intereseciton = Redis::zinterstore(2, $value_range, $span_range);
返回0。
我应该得到的是:
1) {"id":564311,"stock_id":4241,"value":"91.52","span_minutes":7200,"symbol":"NDAQ"}
因为它是原始集合中唯一符合我两个条件的元素。
也许我的语法错误,或者方法完全错误。如何有效地获得两个排序集的交集?
答案 0 :(得分:0)
正如我在评论中提到的,您需要在客户端进行交叉。否则,您必须编写一个Lua脚本来完成这项工作:
--inter.lua
local value_key = KEYS[1]
local span_key = KEYS[2]
local value_min = ARGV[1]
local value_max = ARGV[2]
local span_min = ARGV[3]
local span_max = ARGV[4]
local value_range = redis.call("zrangebyscore", value_key, value_min, value_max)
local span_range = redis.call("zrangebyscore", span_key, span_min, span_max)
-- do intersection
local value_set = {}
for _, item in ipairs(value_range) do
value_set[item] = true
end
local result = {}
for _, item in ipairs(span_range) do
if value_set[item] ~= nil then table.insert(result, item) end
end
return result
像这样运行它:redis-cli --eval inter.lua values spans , 20 100 5000 8000