redisでtwitterのタイムラインのように時系列でデータを保存することを考えてみる。
新しく追加されたデータを先に取得できるようにする必要がある。
ページングするのに、最後に返したデータのポジションは取得できず、データそのものが渡されると仮定。
つまりデータからindexが取得可能である必要がある。
listを使うと頭から走査しないと取得できないので、sorted mapでscoreにシステム時刻を入れることを試してみる。
pythonで操作した。
まず順番に5つのデータを入れてみる
# coding=utf-8 import redis import time client = redis.Redis() KEY = "loglog" VALUES = ["one", "two", "three", "four", "five"] # 初期化 client.delete(KEY) def get_score(): """ 現在時刻をscoreとして取得する関数 """ return int(time.time() * 1000) # 順番に値を追加 for value in VALUES: client.zadd(KEY, value, get_score()) time.sleep(0.1)
この時点でzrangeで全件取得するとscoreの昇順、すなわち古い順で返される
print client.zrange(KEY, 0, -1) # ['one', 'two', 'three', 'four', 'five']
zrevrangeで逆順に取得、新しいものを先に取得できる
print client.zrevrange(KEY, 0, -1) # ['five', 'four', 'three', 'two', 'one']
値を入れなおすと順序が変わる
# 値の更新 client.zadd(KEY, "four", get_score()) # 更新された値が先頭になる print client.zrevrange(KEY, 0, -1) # ['four', 'five', 'three', 'two', 'one']
値からindexを取得してみる。
zrankで値の順位が取得できるが、zrevrankを使えば逆順で取得できる。
idx = client.zrevrank(KEY, "three") # ['four', 'five', 'three', 'two', 'one']なので2が返される
indexからn件取得する処理を考えてみる
# idxの値は含まないので+1 start = idx + 1 n = 2 print client.zrevrange(KEY, start, start + n) # ['two', 'one']
最後にmax件数を決めておいて、超過したら古いを削除する処理を考えてみる
zremrangebyrankが用意されてるがこれを逆順で使うために、maxをマイナスで指定する
# max3件と仮定 _max = 3 client.zremrangebyrank(KEY, 0, -(_max + 1)) print client.zrevrange(KEY, 0, -1) # 古い2件が削除され、全部で3件になった # ['four', 'five', 'three']