Redisでソートされたセットを管理する方法

はじめに

Redisはオープンソースのインメモリのキーバリューデータストアです。Redisでは、ソートされた集合はセットと同様のデータ型であり、両方とも繰り返しのない文字列のグループです。異なる点は、ソートされた集合の各メンバーはスコアと関連付けられており、最小スコアから最大スコアまでソートすることができることです。セットと同様に、ソートされた集合のすべてのメンバーは一意でなければなりませんが、複数のメンバーが同じスコアを共有することができます。

このチュートリアルでは、ソートされたセットの作成方法、メンバーの取得と削除方法、および既存のセットから新しいソートされたセットの作成方法について説明します。

このガイドの使い方

このガイドは、自己完結型の例を使用したチートシートとして書かれています。あなたが完了しようとしているタスクに関連するセクションへ飛ぶことをおすすめします。

このガイドで示されたコマンドは、Redisバージョン6.0.16を実行しているUbuntu 22.04サーバーでテストされました。同様の環境をセットアップする場合は、「Ubuntu 22.04にRedisをインストールしてセキュアにする方法」ガイドのステップ1に従うことができます。これらのコマンドの動作を実証するため、Redisのコマンドラインインターフェースであるredis-cliを使用して実行します。別のRedisインターフェース(例:Redli)を使用している場合、特定のコマンドの出力結果は異なる場合があります。

このガイドでは、これらのコマンドをテストするために管理対象のRedisデータベースインスタンスを用意することもできますが、データベースプロバイダーが許可する制御レベルによっては、一部のコマンドが記載通りに動作しない場合があります。Silicon Cloud Managed Databaseを用意するには、Managed Databases製品のドキュメントに従ってください。その後、Managed DatabaseにTLS経由で接続するには、RedliをインストールするかTLSトンネルを設定する必要があります。

ソートされたセットを作成し、メンバーを追加する。

ソート済みセットを作成するには、zaddコマンドを使用します。zaddコマンドは、ソートされたセットを保持するキーの名前、追加するメンバーのスコア、およびメンバー自体の値を引数として受け入れます。以下のコマンドは、スコアが1である”Joe Pass”という1つのメンバーを持つfaveGuitaristsというキーのソート済みセットを作成します。

  1. zadd faveGuitarists 1 “Joe Pass”

 

もしソート済み集合が正常に作成された場合、zaddは追加されたメンバーの数を示す整数を返します。

Output

(integer) 1

zaddを使用すると、ソートされたセットに複数のメンバーを追加することができます。メンバーのスコアは連続している必要はありませんし、スコア間にはギャップが存在することもあります。また、同じスコアを持つ複数のメンバーが同じソートされたセットに含まれることもあります。

  1. zadd faveGuitarists 4 “Stephen Malkmus” 2 “Rosetta Tharpe” 3 “Bola Sete” 3 “Doug Martsch” 8 “Elizabeth Cotten” 12 “Nancy Wilson” 4 “Memphis Minnie” 12 “Michael Houser”

 

Output

(integer) 8

以下のオプションを指定して、ZADDはキー名の後と最初のメンバースコアの前に入力する必要があります。

  • NX or XX: These options have opposite effects, so you can only include one of them in any zadd operation:NX: Tells zadd not to update existing members. With this option, zadd will only add new elements.
    XX: Tells zadd to only update existing elements. With this option, zadd will never add new members.
  • CH: Normally, zadd only returns the number of new elements added to the sorted set. With this option included, though, zadd will return the number of changed elements. This includes newly added members and members whose scores were changed.
  • INCR: This causes the command to increment the member’s score value. If the member doesn’t yet exist, the command will add it to the sorted set with the increment as its score, as if its original score was 0. With INCR included, the zadd will return the member’s new score if it’s successful. Note that you can only include one score/member pair at a time when using this option.

zaddコマンドにINCRオプションを渡す代わりに、同じように振る舞うzincrbyコマンドを使用することができます。zaddと同様に、ソートされたセットのメンバーにスコア値に示された値を与える代わりに、そのメンバーのスコアをその値だけ増やします。たとえば、次のコマンドは、元々4であったメンバー「Stephen Malkmus」のスコアを5増やして9にします。

  1. zincrby faveGuitarists 5 “Stephen Malkmus”

 

Output

“9”

zaddコマンドのINCRオプションのように、指定したメンバーが存在しない場合、zincrbyはそのスコアとして増分値を持つように作成します。

ソートされたセットからメンバーを取得する

ソートされたセット内のメンバーを取得するために最も基本的な方法は、zrangeコマンドを使用することです。このコマンドは、取得したいメンバーが含まれるキーの名前と、それに含まれるメンバーの範囲を引数として受け取ります。範囲は、ゼロベースのインデックスを表す2つの数字で定義されます。つまり、0はソートされたセット内の最初のメンバー(または、最低スコアのメンバー)を表し、1は次のメンバーを表します。以降同様に続きます。

前のセクションで作成されたfaveGuitaristsのソートされたセットから最初の4人のメンバーを返します。

  1. zrange faveGuitarists 0 3

 

Output

1) “Joe Pass” 2) “Rosetta Tharpe” 3) “Bola Sete” 4) “Doug Martsch”

ソートされたセットをzrangeに渡す場合、スコアが同じ2つ以上の要素がある場合、それらの要素は辞書順(またはアルファベット順)に並べ替えられます。

開始インデックスと終了インデックスは負の数でも構いません。-1は最後の要素を示し、-2は最後から2番目を示すようになります。

  1. zrange faveGuitarists -5 -2

 

Output

1) “Memphis Minnie” 2) “Elizabeth Cotten” 3) “Stephen Malkmus” 4) “Michael Houser”

zrangeは、WITHSCORES引数を受け入れることができます。この引数が含まれると、メンバーのスコアも返されます。

  1. zrange faveGuitarists 5 6 WITHSCORES

 

Output

1) “Elizabeth Cotten” 2) “8” 3) “Stephen Malkmus” 4) “9”

zrangeは、昇順の数字で範囲内のメンバーを返すことしかできません。これを逆にし、降順の範囲を返すには、zrevrangeコマンドを使用する必要があります。このコマンドは、指定された範囲内にあるメンバーを返す前に、与えられたソートされたセットの順序を一時的に反転させるものと考えてください。したがって、zrevrangeでは、0はキーに保持される最後のメンバーを表し、1は直前のメンバーを表し、以降同様です。

  1. zrevrange faveGuitarists 0 5

 

Output

1) “Nancy Wilson” 2) “Michael Houser” 3) “Stephen Malkmus” 4) “Elizabeth Cotten” 5) “Memphis Minnie” 6) “Doug Martsch”

zrevrangeは、WITHSCORESオプションも受け入れることがあります。

zrangebyscoreコマンドを使用すると、スコアに基づいてメンバーの範囲を返すことができます。次の例では、コマンドはスコアが2、3、または4のfaveGuitaristsキーに格納されたメンバーを返します。

  1. zrangebyscore faveGuitarists 2 4

 

Output

1) “Rosetta Tharpe” 2) “Bola Sete” 3) “Doug Martsch” 4) “Memphis Minnie”

この例では、範囲は包括的です。つまり、スコアが2または4のメンバーが返されます。開き括弧(()で範囲の両端を除外することもできます。次の例では、スコアが2以上でかつ4未満のすべてのメンバーが返されます。

  1. zrangebyscore faveGuitarists 2 (4

 

Output

1) “Rosetta Tharpe” 2) “Bola Sete” 3) “Doug Martsch”

zrangebyscoreでもWITHSCORES引数を使用することができます。さらに、LIMITオプションも受け入れており、zrangebyscoreの出力から選択した要素のみを取得することができます。このオプションはオフセットを受け入れます。これはコマンドが返す範囲の最初のメンバーを示し、countはコマンドが合計で返すメンバーの数を定義します。たとえば、以下のコマンドはfaveGuitaristsソートされた集合の最初の6つのメンバーを調べますが、そのうち2番目のメンバーから始まり、合計3つのメンバーのみを返します(1:で表される)。

  1. zrangebyscore faveGuitarists 0 5 LIMIT 1 3

 

Output

1) “Rosetta Tharpe” 2) “Bola Sete” 3) “Doug Martsch”

zrevrangebyscoreコマンドは、スコアに基づいてメンバーの範囲を逆順で返します。次のコマンドは、スコアが10から6の間のセットのすべてのメンバーを返します。

  1. zrevrangebyscore faveGuitarists 10 6

 

Output

1) “Stephen Malkmus” 2) “Elizabeth Cotten”

zrangebyscoreと同様に、zrevrangebyscoreもWITHSCORESおよびLIMITオプションを受け付けることができます。さらに、範囲の両端を開いた括弧で前置することで、範囲のどちらかを除外することもできます。

ソートされたセットのメンバー全員が同じスコアを持つ場合があります。そのような場合、zrangebylexコマンドを使用してRedisに範囲内の要素を辞書式でソートしたり、アルファベット順にして返すことができます。このコマンドを試すために、以下のzaddコマンドを実行して、各メンバーが同じスコアを持つソートされたセットを作成してください。

  1. zadd SomervilleSquares 0 Davis 0 Inman 0 Union 0 porter 0 magoun 0 ball 0 assembly

 

zrangebylexは、キーの名前、開始間隔、終了間隔の順に指定する必要があります。開始間隔と終了間隔は、開いた括弧(())または開いた角括弧([)で始める必要があります。以下のように記述してください。

  1. zrangebylex SomervilleSquares [a [z

 

Output

1) “assembly” 2) “ball” 3) “magoun” 4) “porter”

この例では、セットの8人のメンバーのうち、わずか4人のメンバーが返されたことに注目してください。コマンドはaからzまでの範囲を検索するため、Redisの値は大文字と小文字を区別するため、大文字で始まるメンバーが出力から除外されます。これらを返すためには、以下のコマンドを実行することができます。

  1. zrangebylex SomervilleSquares [A [z

 

Output

1) “Davis” 2) “Inman” 3) “Union” 4) “assembly” 5) “ball” 6) “magoun” 7) “porter”

zrangebylexでは、特殊文字の-(マイナス)はマイナス無限大を、+(プラス)はプラス無限大を表すので、下記のコマンド構文もソートされたセットのすべてのメンバーを返します。

  1. zrangebylex SomervilleSquares – +

 

zrangebylexでは、ソート済みセットのメンバーを逆の辞書順(昇順のアルファベット順)で返すことはできません。その場合は、zrevrangebylexを使用してください。

  1. zrevrangebylex SomervilleSquares + –

 

Output

1) “porter” 2) “magoun” 3) “ball” 4) “assembly” 5) “Union” 6) “Inman” 7) “Davis”

zrangebylexは、すべてのメンバーが同じスコアを持つソートされたセットで使用することを想定しているため、WITHSCORESオプションは受け付けません。ただし、LIMITオプションは受け付けます。

ソートされたセットに関する情報の取得

与えられたソートされたセットのメンバー数を調べるために(つまり、その要素数を求めるために)は、zcard コマンドを使用します。以下の例は、このガイドの最初のセクションで定義された faveGuitarists キーに含まれるメンバーの数を示しています。

  1. zcard faveGuitarists

 

Output

(integer) 9

zcountは、与えられたソート済みセット内においてスコアの範囲内にある要素の数を教えてくれます。キーの次の最初の数字は範囲の開始であり、2番目の数字は範囲の終了です。

  1. zcount faveGuitarists 3 8

 

Output

(integer) 4

zスコアは、ソートされたセットの指定されたメンバーのスコアを出力します。

  1. zscore faveGuitarists “Bola Sete”

 

Output

“3”

指定されたメンバーまたはキーのいずれかが存在しない場合、zscoreは(nil)を返します。

zrankはzscoreに似ていますが、与えられたメンバーのスコアではなく、そのランクを返します。Redisでは、ランクはスコア順に並べられたソートされたセットのメンバーの0から始まるインデックスです。例えば、「Joe Pass」のスコアは1ですが、それがキー内のどのメンバーの最低スコアであるため、それは0のランクを持っています。

  1. zrank faveGuitarists “Joe Pass”

 

Output

(integer) 0

もう一つのRedisコマンドには、zrankと同じ機能を持つzrevrankというものがありますが、このコマンドではセット内のメンバーのランクを逆にします。次の例では、メンバー「Joe Pass」が最低のスコアを持ち、したがって逆順のランクが最も高くなります。

  1. zrevrank faveGuitarists “Joe Pass”

 

Output

(integer) 8

メンバーのスコアとランクの唯一の関係は、他のメンバーのスコアとの比較です。2つの連続するメンバーの間にスコアの差があれば、それはランクには反映されません。ただし、2人のメンバーが同じスコアを持っている場合、アルファベット順に先に来る方が低いランクを持ちます。

zscoreと同様に、zrankとzrevrankも、キーまたはメンバーが存在しない場合には(nil)を返します。

zlexcountは、辞書順の範囲内にあるソートされたセットのメンバーの数を教えてくれます。以下の例では、前のセクションからのSomervilleSquaresというソートされたセットを使用しています。

  1. zlexcount SomervilleSquares [M [t

 

Output

(integer) 5

このコマンドは、zrangebylexコマンドと同じ構文に従いますので、文字列の範囲を定義する方法の詳細については、前のセクションを参照してください。

ソートされた集合からメンバーを削除する

zremコマンドは、ソートされたセットから1つ以上のメンバーを削除することができます。

  1. zrem faveGuitarists “Doug Martsch” “Bola Sete”

 

zremは、ソートされたセットから削除したメンバーの数を表す整数を返します。

Output

(integer) 2

ソートされたセットからメンバーを範囲に基づいて削除するためのRedisコマンドは3つあります。例えば、ソートされたセットの各メンバーが同じスコアを持つ場合、zremrangebylexを使用して辞書順の範囲に基づいてメンバーを削除することができます。このコマンドは、zrangebylexと同じ構文を使用します。以下の例では、前のセクションで作成されたSomervilleSquaresキーから大文字で始まるすべてのメンバーが削除されます。

  1. zremrangebylex SomervilleSquares [A [Z

 

zremrangebylexは、削除されたメンバーの数を示す整数を出力します。

Output

(integer) 3

zremrangebyscoreコマンドを使用すると、zrangebyscoreコマンドと同じ構文を使用して、スコアの範囲に基づいてメンバーも削除できます。以下の例では、スコアが4、5、または6のfaveGuitaristsに保存されているすべてのメンバーを削除します。

  1. zremrangebyscore faveGuitarists 4 6

 

Output

(integer) 1

zremrangebyrankコマンドを使用すると、zrangebyrankと同じ構文を使用して、ランクの範囲に基づいてセットからメンバーを削除することができます。以下のコマンドは、0から始まるインデックスの範囲で定義される最低順位の3つのメンバーをソートされたセットから削除します。

  1. zremrangebyrank faveGuitarists 0 2

 

Output

(integer) 3

remrangebyrankに渡される数値は負の値にすることもできます。-1は最高のランクを表し、-2は次に高いランクを表します。以此類推です。

既存のソート済みセットから新しいソート済みセットを作成する。

Redisには、複数のソートされた集合のメンバーを比較し、それらの比較に基づいて新しい集合を作成するための2つのコマンド、zinterstoreとzunionstoreが含まれています。これらのコマンドを試すために、以下のzaddコマンドを実行していくつかの例のソートされた集合を作成してください。

  1. zadd NewKids 1 “Jonathan” 2 “Jordan” 3 “Joey” 4 “Donnie” 5 “Danny”
  2. zadd Nsync 1 “Justin” 2 “Chris” 3 “Joey” 4 “Lance” 5 “JC”

 

zinterstoreは、2つ以上のソート済みセットで共有されているメンバー(インターセクション)を見つけ、それらのメンバーだけを含む新しいソート済みセットを生成します。このコマンドには、インターセクトメンバーがソート済みセットとして保存される宛先キーの名前、zinterstoreに渡されるキーの数、そして分析したいキーの名前が、順番に含まれている必要があります。

  1. zinterstore BoyBands 2 NewKids Nsync

 

zinterstoreは、宛先のソートされたセットに格納されている要素の数を示す整数を返します。NewKidsとNsyncは、”Joey”というメンバーのみを共有しているため、このコマンドは1を返します。

Output

(integer) 1

もしも宛先のキーが既に存在する場合、zinterstoreはその内容を上書きします。

zunionstoreは、それに渡されたキーのすべての要素を保持する新しいソートされたセットを作成します。このコマンドは、zinterstoreと同じ構文を使用し、コマンドに渡されるキーの数とキーの名前、そして宛先キーの名前が必要です。

  1. zunionstore SuperGroup 2 NewKids Nsync

 

zinterstoreと同様に、zunionstoreも、宛先キーに保管された要素の数を示す整数を返します。元の2つのソート済みセットが共に5つのメンバーを持っていたにも関わらず、ソート済みセットは繰り返しメンバーを持つことができないため、各キーには”Joey”という名前のメンバーが1つずつあるため、結果の整数は9になります。

Output

(integer) 9

zunionstoreは、既に存在する場合、宛先キーの内容を上書きします。

新しいソート済みセットを作成する際に、zinterstoreとzunionstoreの両方のコマンドでメンバースコアに対するより細かな制御を提供するために、WEIGHTSオプションとAGGREGATEオプションを使用できます。

コマンドに含まれるソート済みセットごとに、WEIGHTSオプションの後には数値が続き、それぞれのメンバーのスコアを重み付けします。WEIGHTSオプションの後の最初の数値は、コマンドに渡される最初のキーのスコアに重みを乗じ、2番目の数値は2番目のキーに重みを乗じる、といった具合です。

以下の例は、NewKidsとNsyncのソートされたセットから共通するキーを持つ新しいソートされたセットを作成します。NewKidsキーのスコアには3の係数を掛け、Nsyncキーのスコアには7の係数を掛けます。

  1. zinterstore BoyBandsWeighted 2 NewKids Nsync WEIGHTS 3 7

 

WEIGHTSオプションが含まれていない場合、zinterstoreとzunionstoreの両方の重み付けはデフォルトで1になります。

AGGREGATEは3つのサブオプションを受け入れます。そのうちの最初のオプションであるSUMは、結合したセットの一致するメンバーのスコアを合計することで、zinterstoreとzunionstoreのデフォルトの振る舞いを実装します。

もし2つのソート済みセットに、1つのメンバーが共有されているが、それぞれのセットでスコアが異なる場合、zinterstoreまたはzunionstore操作を実行することで、新しいセットに低いスコアを割り当てるように操作を強制することができます。これは、MINサブオプションを使用します。

  1. zinterstore BoyBandsWeightedMin 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MIN

 

2つのソートされたセットには、スコアが同じ(3)一致するメンバーが1つしかないため、このコマンドは、2つの重み付けスコアのうち低い方を持つメンバーで新しいセットを作成します。

  1. zscore BoyBandsWeightedMin “Joey”

 

Output

“9”

同様に、AGGREGATEはMAXオプションを使用して、zinterstoreまたはzunionstoreによって2つのスコアのうちより高いスコアを割り当てることができます。

  1. zinterstore BoyBandsWeightedMax 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MAX

 

このコマンドは、2つの重み付けスコアのうちで高いスコアを持つ1人のメンバー「ジョーイ」を持つ新しいセットを作成します。

  1. zscore BoyBandsWeightedMax “Joey”

 

Output

“21”

メンバーのスコアを分析する前に、WEIGHTSは一時的に操作する手段と考えると役立ちます。同様に、AGGREGATEオプションは新しいセットに追加される前にメンバーのスコアをどのように制御するかを決定する手段と考えると役立ちます。

結論

このガイドでは、Redisでソートされたセットを作成および管理するために使用されるコマンドのいくつかについて詳しく説明しています。このガイドに関連する他のコマンド、引数、手順について知りたいことがあれば、コメントで質問したり提案したりしてください。

Redisのコマンドに関する詳細な情報は、「Redisデータベースの管理方法」チュートリアルシリーズをご覧ください。

コメントを残す 0

Your email address will not be published. Required fields are marked *