Die Geschichte des Echtzeit-Rankings mit dem Redis Sorted Set wurde bereits zerkratzt, aber es fühlt sich wie eine schnelle Suche an, und ich konnte kein konkretes Implementierungsbeispiel in Python finden, daher vereinfache ich normalerweise die Bibliothek, die ich normalerweise intern verwende. Ich werde es vorstellen.
Source Code
ranking.py
from datetime import timedelta
from .rankinglist import RankingList
_default_expire = int(timedelta(weeks=2).total_seconds())
class Ranking(object):
def __init__(self, client, key, expire=_default_expire):
"""
Initialisieren Sie die Klasse.
:param object client:Redis Client.
:param string key:Ranking-ID.
:param int expire:Ablaufdatum des Rankings.Zwei Wochen, wenn weggelassen.
"""
self._r = client
self._key = key
self._expire = expire
def push(self, unique_id, value):
"""
Aktualisieren Sie das Ranking.
:param string unique_id:ID zum Rang.
:param string value:Ranking Quellwert(Punkte etc.)
"""
self._r.zadd(self._key, long(value), unique_id)
self.touch()
def get_rank(self, unique_id):
"""
Holen Sie sich das Ranking.
:param string unique_id:ID zum Rang.
:return:Rangfolge
"""
value = self._r.zscore(self._key, unique_id)
if value is None:
return None
return self._r.zcount(self._key, '({}'.format(int(value)), 'inf') + 1
def get_range(self, start, end):
"""
Holen Sie sich den Rangbereich.
:param int start:Tiefgestellte Startposition.
:param int end:Endposition des Index. start=0 and end=Bei 0,Holen Sie sich den ersten.
:return: ['push()Einzigartig angegeben in_id', ...]
"""
result = self._r.zrevrange(self._key, start, end)
self.touch()
return result
def get_count(self):
"""
Holen Sie sich die Anzahl der Fälle.
:return:Nummer
"""
return self._r.zcard(self._key)
def touch(self):
"""
Verlängern Sie das Ablaufdatum des Rankings.
push()Und bekomme_rank()Aber es wird ausgeführt.
"""
self._r.expire(self._key, self._expire)
def clean(self):
"""
Ranking löschen.
"""
self._r.delete(self._key)
def gen_list(self, wrapper=None):
"""
Holen Sie sich die Rangliste.
:param function wrapper:Funktion, die das Element umschließt
:return:RankingList-Objekt
RankingList,In gewissem Maße als Liste fungieren.
Wird bei der Übergabe an Paginator of Django usw. verwendet..
"""
return RankingList(self, wrapper)
Ein wenig verwirrend sind get_rank () und gen_list (). gen_rank () zählt die Anzahl der Personen, die höher als die aktuelle Punktzahl sind, um ein Ranking zu erhalten, das die Bindungen berücksichtigt. Das von gen_list () zurückgegebene RankingList-Objekt wird später beschrieben.
rankinglist.py
class RankingList(object):
def __init__(self, rank, wrapper=None):
self._rank = rank
self._wrapper = wrapper
def __getitem__(self, k):
if isinstance(k, slice):
start = k.start if k.start else 0
end = k.stop - 1 if k.stop else self.__len__() - 1
step = k.step
unique_ids = self._rank.get_range(start, end)
if step:
unique_ids = unique_ids[::step]
return [self._wrap(unique_id) for unique_id in unique_ids]
else:
if self.__len__() <= k:
raise IndexError('list index out of range')
unique_ids = self._rank.get_range(k, k)
return self._wrap(unique_ids[0])
def _wrap(self, unique_id):
return self._wrapper(unique_id) if self._wrapper else unique_id
def __len__(self):
return self._rank.get_count()
Delegieren Sie das Ranking an eine RankingList, die sich wie eine Python-Liste verhält. Durch Übergeben von Wapper wird außerdem ein Objekt generiert und basierend auf der aus Redis extrahierten unique_id zurückgegeben.
>>> from redis import Redis
>>> from ranking import Ranking
>>>
>>> ranking = Ranking(Redis(), 'event1')
>>>
>>> ranking.push('p1', 200)
>>> ranking.push('p2', 100)
>>> ranking.push('p3', 300)
>>> ranking.push('p1', 1000)
>>> ranking.push('p4', 1000)
>>>
>>> l1 = ranking.gen_list() # ['p4', 'p1', 'p3', 'p2']
>>> l1[2:] # ['p3', 'p2']
>>>
>>> import Player # e.g. Django Model
>>> def wrapper(id):
return Player.objects.get(pk=id)
>>> l2 = ranking.gen_list(wrapper) # [Player('p4'), Player('p1'), Player('p3'), Player('p2')]
>>> l2[2:] # [Player('p3'), Player('p2')]
>>>
>>> [ranking.get_rank(player_id) for player_id in l1] # [1, 1, 2, 3]
Recommended Posts