Redis ZINTERSTORE нескольких ZRANGEBYSCORE в одном вызове команды? - PullRequest
0 голосов
/ 14 июня 2019

Вопрос об этих командах Redis и о том, как использовать 3 ° и 4 ° в одном вызове.

1)

HMSET key field value [field value ...]

2)

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

3)

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

4)

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]

у меня есть тысяча точек с координатами x y z: p1, p2, p3, p4, p5, p6, p7 ...

HMSET p_1 x 10 y 20 z 30
HMSET p_2 x 20 y 30 z 40
HMSET p_3 x 30 y 40 z 50
...
...

У меня есть три отсортированных набора: xsorted, ysorted, zsorted

zadd xsorted 10 p_1
zadd xsorted 20 p_2
zadd xsorted 30 p_3
... 

(все x как баллы и ключи очков p_1, p_2, p_3 ... как участники

zadd ysorted 20 p_1
zadd ysorted 30 p_2
zadd ysorted 40 p_3
....

(все y как баллы и ключи очков p_1, p_2, p_3 ... как члены

zadd zsorted 30 p_1
zadd zsorted 40 p_2
zadd zsorted 50 p_3
...

(все z в виде баллов и ключи точек p_1, p_2, p_3 ... в качестве членов

У меня есть range_x, range_y, range_z на стороне клиента как результаты ZRANGEBYSCORE:

range_x = ZRANGEBYSCORE xsorted min max    
range_y = ZRANGEBYSCORE ysorted min max 
range_z = ZRANGEBYSCORE zsorted min max 

У меня xyzinter на стороне клиента в результате ZINTERSTORE:

ZINTERSTORE xyzinter 3 range_x range_y range_z

Таким образом, xyzinter имеет ключи точек с координатами x, y, z в диапазоне значений. Хорошо, мне это нужно.

Существует возможность более быстрого выполнения описанных выше команд только с двумя вызовами?

Что-то вроде:

1)

ZINTERSTORE xyzinter 3 
ZRANGEBYSCORE xsorted min max    
ZRANGEBYSCORE ysorted min max 
ZRANGEBYSCORE zsorted min max 

2)

ZRANGE xyzinter start stop

Заранее спасибо Mario

Ответы [ 2 ]

0 голосов
/ 14 июня 2019

Лучшее решение, чем я нашел: Используя три массива "sort_id", созданных в начале в Ruby, перед сохранением его как отсортированных наборов в Redis. Я получаю только Redis мин, макс. ~ 100 точек / сек с тремя результирующими отсортированными массивами для пересечения с 30-40 элементами каждый. Но все еще слишком медленно (Ruby на стороне клиента)

def points_id_in_range crng

    sort_key=[:x=>"sort_x",:y=>"sort_y",:z=>"sort_z"]
    rrng = {:x=>[],:y=>[],:z=>[]}

    [:x,:y,:z].each{|sym|

        rrng[sym] << $r.ZRANGEBYSCORE(sort_key[sym], crng[sym].min, 
        crng[sym].max, :LIMIT,0,1)[0].to_i

        rrng[syn] << $r.ZREVRANGEBYSCORE(sort_key[sym], 
        crng[sym].max, crng[sym].min, :LIMIT,0,1)[0].to_i

    }

    #intersection in Ruby

    @@sort_id[:x][rrng[:x].min..rrng[:x].max] &
    @@sort_id[:y][rrng[:y].min..rrng[:y].max] &
    @@sort_id[:z][rrng[:z].min..rrng[:z].max] 

end
0 голосов
/ 14 июня 2019

Нет, вам придется вызывать обе команды. Однако вы можете обернуть их в скрипт Lua, который будет запускаться на стороне сервера, и тогда ваш клиент сделает один вызов Redis. Узнайте больше о сценариях Lua в Redis на https://redis.io/commands/eval

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