お手軽さとパフォーマンスの噂を聞いて Redis を使い始めたわけですが、RDB のようなクエリをしようとすると、当然、利用者側でなんとかする必要があります。たぶん、こうやればいいのかなぁという感じで。
クイズの回答を Redis に保存しようとしています。「各 user は、各 quiz に多くとも1つだけ回答できる。ただし、上書きができる。」という前提です。こんな JSON でデータを保存しましょう。
{"quiz": "1", "user": "alice", "ans": "X", ...}
{"quiz": "2", "user": "alice", "ans": "Y", ...}
{"quiz": "1", "user": "bob", "ans": "X", ...}
必要なクエリは以下のとおり。
- quiz=1 に回答したユーザを取得する。
- quiz=1 に、ans=X と回答したユーザを取得する。
- user=alice の回答を取得する。
データ構造
データ本体を保持するハッシュ
quiz:1:user, alice => {...}
クイズ番号と回答の組み合わせごとのユーザを保持するセット
index:quiz:1:ans:X:users => (alice, bob)
ユーザが回答したクイズ番号を保持するセット
Index:user:alice:quizzes => (1, 2)
> HSET quiz:1:user alice '{...}'
(integer) 1
> SADD index:quiz:1:answer:X:users alice
(integer) 1
> SADD index:user:alice:quizzes 1
(integer) 1
残りふたつの回答も同様に。
> HSET quiz:2:user alice '{...}'
> SADD index:quiz:2:answer:Y:users alice
> SADD index:user:alice:quizzes 2
> HSET quiz:1:user bob '{...}'
> SADD index:quiz:1:answer:X:users bob
> SADD index:user:bob:quizzes 1
クイズ番号とユーザ名から、任意の回答を取得できます。
> HGET quiz:1:user alice
"{...}"
quiz=1 の回答、回答数、および回答したユーザは、このハッシュから取り出します。
> HGETALL quiz:1:user
1) "alice"
2) "{…}"
3) "bob"
4) "{…}"
> HLEN quiz:1:user
(integer) 2
> HKEYS quiz:1:user
1) "alice"
2) "bob"
quiz=1 かつ ans=X の回答数、回答したユーザ、回答は index:quiz:1:answer:X:users セットから取り出します。
> SCARD index:quiz:1:answer:X:users
(integer) 2
> SMEMBERS index:quiz:1:answer:X:users
1) "alice"
2) "bob"
> HMGET quiz:1:user alice bob # クイズ番号とユーザ名を使って、ハッシュから取得
1) "{…}"
2) "{…}"
user=alice の回答数、クイズ番号、回答は index:user:alice:quizzes セットから取得します。
> SCARD index:user:alice:quizzes
(integer) 2
> SMEMBERS index:user:alice:quizzes
1) "1"
2) "2"
> HGET quiz:1:user alice
"{…}"
削除するときには、ハッシュと2つのセットを削除します。
> HDEL quiz:1:user alice
(integer) 1
> SREM index:quiz:1:answer:X:users alice
(integer) 1
> SREM index:user:alice:quizzes 1
(integer) 1
と、こんなやりかたで考えています。筋がいいことを願う。