技術

Redisでソート

一部でRedisがアツいということで触ってみました。
SQLとはかなり違ってて理解するのに少し苦労しました。
忘れないようにソートに関連する処理の方法を2パターン書いておきます。

なお、Redisの使い方はまだ1時間程度しか調べてないですし、NoSQL自体始めてなので、「ソートはこうやるんだよ」的なエントリではなくて「こうやったらソートできたんだけどこれでいいの?教えてエロイ人」的なエントリですので、指摘/補足などあるとありがたいです。

使ってるのはRedis 1.2.6 + redis-py 1.34.1 + Python 2.7です。

1. idのセットとスコアリング用のデータを別に用意する方法(普通のsetを使う方法)

import redis, random

# Redisサーバーに接続
r = redis.Redis(host='127.0.0.1', port=6379, db=0)

# ソート用のデータを生成
for id in xrange(100):
	score = random.randint(0, 100)
	r.sadd('set_of_ids', id)
	r.set('score_' + str(id), score)
	r.set('value_' + str(id), 'id: %d, score: %d' % (id, score))

# scoreの高い順にソートして最初の20件idのみ表示
for id in r.sort('set_of_ids', by='score_*', desc=True, start=0, num=20) or []:
	print id

# scoreの高い順にソートして最初の20件の値を表示
for v in r.sort('set_of_ids', by='score_*', get='value_*', desc=True, start=0, num=20) or []:
	print v

# 使ったデータの削除
r.delete('set_of_ids')
for k in r.keys('score_*') + r.keys('value_*'):
	r.delete(k)

2. idのセットとスコアリング用のデータを一度に用意する方法(ソート済みsetを使う方法)

import redis, random

# Redisサーバーに接続
r = redis.Redis(host='127.0.0.1', port=6379, db=0)

# ソート用のデータを生成
for id in xrange(100):
	score = random.randint(0, 100)
	r.zadd('sorted_set_of_ids', str(id), score)
	r.set('value_' + str(id), 'id: %d, score: %d' % (id, score))

# scoreの高い順にソートして最初の20件idのみ表示
for id in r.zrange('sorted_set_of_ids', 0, 20 - 1, desc=True) or []:
	print id

# scoreの高い順にソートして最初の20件の値を表示
for v in r.mget(['value_' + str(id) for id in r.zrange('sorted_set_of_ids', 0, 20 - 1, desc=True) or []]):
	print v

# 使ったデータの削除
r.delete('sorted_set_of_ids')
for k in r.keys('value_*'):
	r.delete(k)

ソート済みsetを使うほうがキーのソートには向いているような気がしますが、値まで取得するとなると、一度キーのリストをPython側で受け取るため美しくない気が。
普通のsetはソートで値まで取得する処理が一度に書けますが、キーを無駄に消費してる気がしなくもない。

Redisもredis-pyもバージョン2系のモノが出てますので、そっちを使うともっとスマートに書けるのかも。

今回はテストなのでscoreをランダムな値にイキナリ設定してますが、実際はscoreを上昇させるタイミングで、r.incr(‘score_’ + str(id))や、r.zincrby(‘sorted_set_of_ids’, str(id)) を使うのが普通かと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください