2012-07-29 13 views
5

Considere un Redis ordenados conjunto con los siguientes miembros:inversa paginación a través de un Redis Ordenado Conjunto

ZADD mySortedSet 11 "A" 
ZADD mySortedSet 21 "B" 
ZADD mySortedSet 32 "C" 
ZADD mySortedSet 46 "D" 
ZADD mySortedSet 53 "E" 
ZADD mySortedSet 68 "F" 
ZADD mySortedSet 72 "G" 
ZADD mySortedSet 82 "H" 
ZADD mySortedSet 94 "I" 
ZADD mySortedSet 104 "J" 
ZADD mySortedSet 113 "K" 

Si yo quiero hacer la paginación en orden inverso, empezando en una rebanada arbitraria, que puede comenzar con esto:

// Returns G, F, E, as expected. 
ZREVRANGEBYSCORE mySortedSet 72 (46 

Ahora, sabiendo solamente que mi límite superior es de 46 años, puedo conseguir los 3 puntos anteriores en el conjunto, D, C, B y, sin saber el límite inferior haciendo:

ZREVRANGEBYSCORE mySortedSet 46 -inf LIMIT 0, 3 

Mi pregunta es, ¿cómo puedo obtener los próximos 3 elementos en el conjunto, J, I y H, en ese orden, sabiendo solo que el límite superior es 72?

// Good start, returns K, J, I, H 
ZREVRANGEBYSCORE mySortedSet +inf (72 

// Returns K, J, I, due to the offset of 0. I don't know what the correct offset is because it's from the start of the range, not the end. 
ZREVRANGEBYSCORE mySortedSet +inf (72 LIMIT 0, 3 

Lo que creo que quiero es un desplazamiento negativo, que no creo que sea compatible.

// Would return J, I, H, but actually returns an empty set. 
ZREVRANGEBYSCORE mySortedSet +inf (72 LIMIT -1, 3 

que se puede fingir con un rango de avance, y luego revertir esos artículos, pero estoy en busca de una solución nativa Redis, si es que existe.

// Returns H, I, J - the items I want, but reversed. 
ZRANGEBYSCORE mySortedSet (72 +inf LIMIT 0, 3 

¿Alguna idea?

Para ser claro, sé que hay ZRANGE y ZREVRANGE, pero en este perfil de consulta, no sabré el índice real, solo el puntaje.

+0

No hay una manera simple de hacerlo. Veo tres opciones. (1) Invertir en su cliente (2) revertir usando LUA (3) usar ZCOUNT para conocer la cantidad de elementos y restar desde allí como un reemplazo de los índices negativos. – seppo0010

+0

Hey seppo0010, gracias por su aporte. Actualmente estoy haciendo 1, y solo quería ver si había una mejor manera. No es partidario de los scripts de LUA para algo como esto, pero ciertamente considerará el enfoque ZCOUNT, ya que la consulta se ejecuta dentro de MULTI, por lo que seguirá siendo atómica. – majelbstoat

Respuesta

1

Es trivial obtener el rango para un elemento, y luego trabajar por índices. Suponiendo que las únicas entradas disponibles para su aplicación son los límites puntuación inicial de 72 y 46, se puede hacer esto:

redis 127.0.0.1:6379> ZREVRANGEBYSCORE mySortedSet 72 (46 
1) "G" 
2) "F" 
3) "E" 
redis 127.0.0.1:6379> ZREVRANK mySortedSet G 
(integer) 4 
redis 127.0.0.1:6379> ZREVRANGE mySortedSet 1 3 
1) "J" 
2) "I" 
3) "H" 
redis 127.0.0.1:6379> 

La única llamada adicional es el O (log (n)) ZREVRANK llamada. A partir de ahí, es un poco de matemática del lado del cliente obtener los nuevos índices para el rango que le interesa, y ZREVRANGE para obtener los valores que desea.

He probado esto en Redis 2.6rc5, pero debería funcionar en cualquier versión superior a 2.0.

+0

Gracias, esto parece un enfoque razonable también. El único problema es que tendría que dividir la solicitud en varias llamadas, o bien escribir un script LUA para manejar el cálculo del rango intermedio. Dependiendo del perfil de los datos, O (log (N)) donde N, la cardinalidad del conjunto es grande, también podría llevar más tiempo que simplemente invertir un "rango ordenado hacia delante", que tendrá M, el recuento de los devueltos – majelbstoat

+0

Sí, dependiendo del tamaño de tus datos, agarrarlo todo e invertirlo podría ser mejor; no olvide, sin embargo, termina pagando los costos de transferencia de red por lo que no usa. Desafortunadamente, la canalización no le ofrece mucho, ya que necesita los valores intermedios para generar consultas posteriores. No estoy seguro de qué otras opciones le faltan para rediseñar las cosas en sentido ascendente para proporcionar diferentes entradas. –

Cuestiones relacionadas