RedisのZUNIONSTORE、ZINTERSTORE を理解する


公式ドキュメントのZUNIONSTOREZINTERSTOREに書いてあるけれど、図解しないとわかりにくいと思います。

前提

私の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(重み)オプションです。(この説明わかるのか…?)

ZUNIONSTOREZINTERSTOREに対する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に対して、適当にWEIGHTSAGGREGATE 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の大きさを比較するんですね。

おわり