2012-07-29 5 views
5

ein Redis Betrachten sortierte mit den folgenden Mitgliedern gesetzt:Reverse-Paginierung Durch Einen Redis Sortiert Set

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" 

Wenn ich Paginierung in umgekehrter Reihenfolge tun mag, an einer beliebigen Scheibe ausgehend ich damit anfangen kann:

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

Nun wissen nur, dass meine obere Grenze ist 46, kann ich die vorherigen drei Elemente in der Reihe bekommen, D, C und B, ohne indem Sie die unteren Grenze zu wissen:

ZREVRANGEBYSCORE mySortedSet 46 -inf LIMIT 0, 3 

Meine Frage ist, wie bekomme ich die nächsten 3 Elemente in der Reihe, J, I und H, in dieser Reihenfolge, nur zu wissen, dass die Obergrenze 72 ist?

Was ich denke, ich will, ist ein negativer Offset, was ich glaube nicht unterstützt wird.

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

kann ich vortäuschen mit einem vorderen Bereich, und dann diese Elemente umgekehrt, aber ich bin auf der Suche für eine native Redis Lösung, falls vorhanden.

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

Irgendwelche Ideen?

Um klar zu sein, ich weiß, es gibt ZRANGE und ZREVRANGE, aber in diesem Abfrageprofil werde ich nicht den tatsächlichen Index, nur die Punktzahl kennen.

+0

Es gibt keine einfache Möglichkeit, dies zu tun. Ich sehe drei Möglichkeiten. (1) Reverse auf Ihrem Client (2) Reverse mit LUA (3) verwenden Sie ZCOUNT, um die Anzahl der Elemente kennen und subtrahieren von dort als Ersatz für negative Indizes. – seppo0010

+0

Hey seppo0010, danke für deine Eingabe. Mache gerade 1 und wollte nur sehen, ob es einen besseren Weg gibt. Kein Fan von LUA-Skripten für so etwas, wird aber sicherlich den ZCOUNT-Ansatz berücksichtigen, da die Abfrage innerhalb von MULTI ausgeführt wird, so dass sie atomar bleibt. – majelbstoat

Antwort

1

Es ist trivial, den Rang für ein Element zu erhalten und dann nach Indizes zu arbeiten. Vorausgesetzt, dass die einzigen Eingänge zur Verfügung zu Ihrer Anwendung sind die ersten Punktzahl Grenzen von 72 und 46, können Sie dies tun:

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> 

Der einzige zusätzliche Aufruf ist die O (log (N)) ZREVRANK Anruf. Von dort ist es ein bisschen clientseitige Mathematik, um die neuen Indizes für den Bereich zu erhalten, an dem Sie interessiert sind, und ZREVRANGE, um die gewünschten Werte zu erhalten.

Ich habe dies auf Redis 2.6rc5 getestet, aber es sollte auf jeder Version über 2.0 funktionieren.

+0

Danke, das sieht nach einem vernünftigen Ansatz aus. Das einzige Problem ist, dass ich die Anforderung in mehrere Aufrufe aufteilen oder ein LUA-Skript schreiben müsste, um den Zwischenbereich zu berechnen. Abhängig von dem Profil der Daten, O (log (N)) wobei N die Kardinalität des Satzes groß ist, könnte es auch zeitaufwendiger sein, als einfach einen "vorwärts geordneten Bereich" umzukehren, der M, die Zählung, haben wird der zurückgegebenen. – majelbstoat

+0

Ja, je nachdem, wie groß Ihre Daten sind, könnte es besser sein, alles zu reversieren und umzukehren; Vergessen Sie aber nicht, dass Sie am Ende die Kosten für die Übertragung des Netzwerks für das bezahlen, was Sie nicht nutzen. Leider bringt das Pipelining hier nicht viel, da Sie die Zwischenwerte benötigen, um die nachfolgenden Abfragen zu erstellen. Sie sind sich nicht sicher, welche anderen Optionen Sie haben, um die Dinge stromaufwärts neu zu gestalten, um verschiedene Eingaben bereitzustellen. –