Получение пересечения двух наборов Redis в Laravel - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть набор, похожий на этот (за исключением того, что в нем около 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"}

потому что это единственный элемент исходного набора, который соответствует обоим моим условиям.

Возможно, у меня неправильный синтаксис или вообще неправильный подход. Как эффективно получить пересечение двух отсортированных наборов?

1 Ответ

0 голосов
/ 19 сентября 2018

Как я уже упоминал в комментариях, вам нужно сделать пересечение на стороне клиента.В противном случае вам нужно написать скрипт 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...