公式ドキュメントのZUNIONSTOREとZINTERSTOREに書いてあるけれど、図解しないとわかりにくいと思います。
前提
私のSortedSetに対する理解の仕方について
私は、SortedSetをこのように理解しているので、そのつもりでお願いします。
このページで使用する、サンプルデータ
説明用に、事前に以下のように2つのSortedSetレコードを準備したことにします。
ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset1 3 "three"
ZADD zset2 11 "one"
ZADD zset2 33 "three"
ZADD zset2 44 "four"
表にすると、各レコード(変数)は以下のようになってます。
縦軸にkey、横軸にmember、値がScoreです。
| ↓member\key→ | zset1 | zset2 |
|---|---|---|
| one | 1 | 11 |
| two | 2 | (nil) |
| three | 3 | 33 |
| four | (nil) | 44 |
基本
Union(和集合)とかIntersect(共通集合)をして、Store(保存)します。デフォだと、各レコードにあるScoreを足し算します。
ミニマルな文法は、以下の通りです。
ZUNIONSTORE destination numkeys key [key ...]
ZINTERSTORE destination numkeys key [key ...]
-
distinationは、出力先のkey名 -
numは、Union・IntersectしたいSortedSetの数 -
keyは、Union・IntersectしたいSortedSetのKey名
ZUNIONSTORE(和集合)の例
ZUNIONSTORE union1 2 zset1 zset2
これをやると、以下の表のようになります。
| ↓member\key→ | zset1 | zset2 | union1 |
|---|---|---|---|
| one | 1 | 11 | → 12 |
| two | 2 | (nil) | → 2 |
| three | 3 | 33 | → 39 |
| four | (nil) | 44 | → 44 |
SortedSetは常にScoreでソートされるので、以下のようになります。
ZRANGE union1 0 -1 WITHSCORES
1) "two"
2) "2"
3) "one"
4) "12"
5) "three"
6) "36"
7) "four"
8) "44"
ZINTERSTORE(共通集合)の例
ZINTERSTORE inter1 2 zset1 zset2
これをやると、以下の表のようになります。
| ↓member\key→ | zset1 | zset2 | inter1 |
|---|---|---|---|
| one | 1 | 11 | → 12 |
| two | 2 | (nil) | → (nil) |
| three | 3 | 33 | → 39 |
| four | (nil) | 4 | → (nil) |
どうなってるか、確認してみます。
ZRANGE inter1 0 -1 WITHSCORES
1) "one"
2) "12"
3) "three"
4) "36"
各種オプション
UNIONとINTERSECTが何かはわかったと思うので、オプションはUNIONで説明します。(公式ドキュメントも、INTERSECTの方には「UNIONのほう見て」って書いてあるし。)
WEIGHTSオプション
各keyに対するWEIGHTS(重み)オプションです。(この説明わかるのか…?)
ZUNIONSTOREとZINTERSTOREに対するWEIGHTSの文法は、以下の通りです。
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]
…まぁ、同じですな。
-
weightは、keyと同じ数になります。
WEIGHTSオプションを使うとどうなるか
以下のようにやってみましょう。
ZUNIONSTORE union2 2 zset1 zset2 WEIGHTS 2 7
これをやると、以下の表のようになります。
| ↓member\key→ | zset1(×2) | zset2(×7) | union2 |
|---|---|---|---|
| one | 1×2 | 11×7 | → 79 |
| two | 2×2 | (nil) | → 4 |
| three | 3×2 | 33×7 | → 237 |
| four | (nil) | 44×7 | → 308 |
SortedSetは、Scoreで常にソートされるので、以下のようになります。
ZRANGE union2 0 -1 WITHSCORES
1) "two"
2) "4"
3) "one"
4) "79"
5) "three"
6) "237"
7) "four"
8) "308"
AGGREGATEオプション
「基本」の説明で、以下のように書きました。
デフォだと、各レコードにあるScoreを足し算します。
この挙動を変更するオプションです。
このオプションの文法は、以下の通りです。
ZINTERSTORE destination numkeys key [key ...] [AGGREGATE SUM|MIN|MAX]
ZUNIONSTORE destination numkeys key [key ...] [AGGREGATE SUM|MIN|MAX]
例によって、同じです。
AGGREGATEオプションを使うとどうなるか
以下のようにやってみましょう。
ZUNIONSTORE union3 2 zset1 zset2 AGGREGATE MIN
AGGREGATE MIN としているので、小さいほうが選ばれます。
| ↓member\key→ | zset1(×2) | zset2(×7) | union2 |
|---|---|---|---|
| one | 1 | 11 | → 1 |
| two | 2 | (nil) | → 2 |
| three | 3 | 33 | → 3 |
| four | (nil) | 44 | → 44 |
ZRANGE union3 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "44"
全部合わせてみる
最後に、4つのSortedSetに対して、適当にWEIGHTSとAGGREGATE MAXを使った場合の例を載せておきます。
ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset1 3 "three"
ZADD zset2 11 "one"
ZADD zset2 33 "three"
ZADD zset2 44 "four"
ZADD zset3 12 "one"
ZADD zset3 inf "three"
ZADD zset3 0 "four"
ZADD zset4 inf "one"
ZADD zset4 33 "three"
ZINTERSTORE inter4 4 zset1 zset2 zset3 zset4 WEIGHTS 13 1 1 0 AGGREGATE MAX
| ↓member\key→ | zset1(×13) | zset2(×1) | zset3(×1) | zset4(×0) | inter4 |
|---|---|---|---|---|---|
| one | 1×13 | 11×1 | 12×1 | inf×0 | →13 |
| two | 2×13 | (nil) | (nil) | (nil) | →(nil) |
| three | 3×13 | 33×1 | inf×1 | 33×0 | → inf |
| four | (nil) | 44×13 | 0×1 | (nil) | →(nil) |
ZRANGE inter4 0 -1 WITHSCORES
1) "one"
2) "13"
3) "three"
4) "inf"
なるほど、WEIGHTSの演算結果で、Scoreの大きさを比較するんですね。