Railsで使うRedisのコマンドについてまとめてみた（Part1: Sets）

# 概要
Redisのメソッドはhttp://redis.io/commands/ にあるように大量にあるので１つずつ和訳して見た。
ついでにrailsでそのコマンドをどう使うかについても記す。
英語に不自由ない方は、直接ドキュメント見ていただいた方が正確かと。

Redisの導入については、[Rails + Redis + AWSでPV数を保存](http://qiita.com/u651601f/items/a0624601047db4f02808)を参照していただきたく。


Part1では[Sets](http://redis.io/commands/#set)のコマンド郡についてまとめる。


# [Sets](http://redis.io/commands/#set)の主な用途
 - (key,value)のペアに対して、valueの方に値を重複なく突っ込みたい場合
    - 「お気に入りリスト」などに使う場合
 - とりあえず集合知（配列）状のデータを扱いたい場合

# コマンド詳細
基本的には、http://redis.io/commands/#set に載っているものを翻訳してみただけです。
## [SADD(値の追加)](http://redis.io/commands/sadd)
計算量：O(N) Nは挿入される要素の数
(key,value)のkeyに対し、値を追加するときに使う。一度追加されたものは、重複して追加されない。（重複関係なしにデータが）うまく追加できなかった時にエラーを返す。
(railseのラッパーでは1つしか挿入できない)

### 戻り値
Integer:新規で挿入できた値の個数を返す。
重複した値を挿入しようとし、新規で追加されない場合、0を返す。
(railsのラッパーを通すとtrue,falseで返る)

### 使用例
```
pry(main)> Redis.current.sadd('key', 'yamada')
=> true
pry(main)> Redis.current.sadd('key', 'genki')
=> true
pry(main)> Redis.current.sadd('key', 'yamada')
=> false
pry(main)> Redis.current.sadd('key', 'yamada')
=> false
pry(main)> Redis.current.smembers('key')
=> ["yamada", "genki"]
pry(main)> Redis.current.sadd('key', 'yamada', 'owata')
ArgumentError: wrong number of arguments (3 for 2)
from /vagrant/www/job-medley/vendor/bundle/ruby/2.2.0/gems/redis-3.2.1/lib/redis.rb:1230:in `sadd'
```

## [SCARD(値の個数確認)](http://redis.io/commands/scard)
計算量：O(1)
(key,value)のkeyに対し、保存されている値の個数を返す。

### 戻り値
Integer:keyに保存されている値の個数を返す。keyがなければ0を返す。

### 使用例
```
pry(main)> Redis.current.sadd('key', 'yamada')
=> true
pry(main)> Redis.current.sadd('key', 'genki')
=> true
pry(main)> Redis.current.sadd('key', 'yamada')
=> false
pry(main)> Redis.current.scard('key')
=> 2
pry(main)> Redis.current.scard('yamada')
=> 0
```

## [SDIFF(データの差分)](http://redis.io/commands/sdiff)
計算量：O(N) Nは渡されるすべての要素の数
複数の(key,value)データに対して、そのvalueの差を返す。
比較はいくつでもでき、1つめに指定したkeyにしか含まれないvalueが返る。

### 戻り値
Array: 差分となるリストを返す(1つ目に指定したkeyにのみ含まれるものを返す)

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sdiff('a','b')
=> ["2", "4", "5"]
pry(main)> Redis.current.sdiff('a','b','c')
=> ["2", "5"]
```

## [SDIFFSTORE(データの差分を保存)](http://redis.io/commands/sdiffstore)
計算量：O(N) Nは渡されるすべての要素の数
基本的には[SDIFF(データの差分)](http://redis.io/commands/sdiff)と同じ。
新しいkeyを指定し、そのkeyに差分となるデータを保存してくれる。
keyが既に存在していた場合は、上書きされる。

### 戻り値
Integer: 差分となるリストに含まれる要素の個数

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sdiffstore('ab', 'a','b')
=> 3
pry(main)> Redis.current.sdiffstore('abc', 'a','b', 'c')
=> 2
pry(main)> Redis.current.smembers('ab')
=> ["2", "4", "5"]
pry(main)> Redis.current.smembers('abc')
=> ["2", "5"]
```

## [SINTER(重複した要素)](http://redis.io/commands/sinter)
計算量：O(N*M) 基本的に１つずつ比較するので、最悪N*M
渡された(key,value)のデータ間で、重複した要素を配列で返してくれる。
keyが存在しない場合は、空のデータとして認識される。
その場合、戻り値も空の配列。

### 戻り値
Array: 重複した要素の配列を返す。

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sinter('a','b')
=> ["1", "3"]
pry(main)> Redis.current.sinter('a','c')
=> ["1", "4"]
pry(main)> Redis.current.sinter('a','b','c')
=> ["1"]
pry(main)> Redis.current.sinter('a','b','yamadagenki')
=> []
```

## [SINTERSTORE(重複した要素の保存)](http://redis.io/commands/sinterstore)
計算量：O(N*M) 基本的に１つずつ比較するので、最悪N*M
[SDIFF(データの差分)](http://redis.io/commands/sdiff)と[SDIFFSTORE(データの差分を保存)](http://redis.io/commands/sdiffstore)の関係と同じ。
[SINTER(重複した要素)](http://redis.io/commands/sinter)の結果を新しいkeyに保存する。
keyが既に存在していた場合は、上書きされる。

### 戻り値
Integer: 共通となる要素リストに含まれる要素の個数

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sinterstore('ab', 'a','b')
=> 2
pry(main)> Redis.current.sinterstore('abc', 'a','b','c')
=> 1
pry(main)> Redis.current.smembers('ab')
=> ["1", "3"]
pry(main)> Redis.current.smembers('abc')
=> ["1"]
```


## [SISMEMBER(要素の存在確認)](http://redis.io/commands/sismember)
計算量：O(1)
指定された要素が、指定されたkeyのvalueに含まれるかどうかを返す

### 戻り値
Integer: 
含まれる場合→1(railsのラッパーを使った場合はtrue)
含まれない場合→0(railsのラッパーを使った場合はfalse)

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.sismember('a', '2')
=> true
pry(main)> Redis.current.sismember('a', '6')
=> false
```

## [SMEMBERS(すべての要素抽出)](http://redis.io/commands/smembers)
計算量：O(N) Nはkeyに含まれる要素数
指定されたkeyに含まれる要素

### 戻り値
Integer: 
含まれる場合→1(railsのラッパーを使った場合はtrue)
含まれない場合→0(railsのラッパーを使った場合はfalse)

### 使用例
```
pry(main)> Redis.current.sadd('a', '1')
=> true
pry(main)> Redis.current.sadd('a', '2')
=> true
pry(main)> Redis.current.smembers('a')
=> ["1", "2"]
```

## [SPOP(1要素のランダム抽出・削除)](http://redis.io/commands/spop)
計算量：O(1)
指定されたkeyに含まれる1つないし、複数の要素を削除する。
（ドキュメント読む限り）LIFOではなく、ランダムな要素が削除される
[SRANDMEMBER(要素のランダム抽出)](http://redis.io/commands/srandmember)とは違い、削除まで行う。

(railsのラッパーでは、一つずつしか取り出せない)

### 戻り値
STRING:要素がある場合は要素を、ない場合はnil

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4"]
pry(main)> Redis.current.spop('a')
=> "2"
pry(main)> Redis.current.spop('a')
=> "3"
pry(main)> Redis.current.spop('a', 4)
ArgumentError: wrong number of arguments (2 for 1)
from /vagrant/www/job-medley/vendor/bundle/ruby/2.2.0/gems/redis-3.2.1/lib/redis.rb:1270:in `spop'
pry(main)> Redis.current.spop('a')
=> "1"
pry(main)> Redis.current.spop('a')
=> "4"
pry(main)> Redis.current.spop('a')
=> nil
```

## [SRANDMEMBER(要素のランダム抽出)](http://redis.io/commands/spop)
計算量：O(N) 抽出する数
指定されたkeyに含まれる1つないし、複数の要素をランダムに抽出する。
正の数が指定されたら、重複なしの値が抽出される。
負の数が指定されたら、重複する値が抽出される。

(railsのラッパーでは、一つずつしか取り出せない)

### 戻り値
STRING:要素がある場合は要素を、ない場合はnil

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.srandmember('a')
=> "2"
pry(main)> Redis.current.srandmember('a')
=> "5"
pry(main)> Redis.current.srandmember('a')
=> "1"
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.srandmember('yamadagenki')
=> nil
pry(main)> Redis.current.srandmember('a', 5)
Redis::CommandError: ERR wrong number of arguments for 'srandmember' command
from /vagrant/www/job-medley/vendor/bundle/ruby/2.2.0/gems/redis-3.2.1/lib/redis/client.rb:113:in `call'
```

## [SREM(指定要素の削除)](http://redis.io/commands/srem)
計算量：O(N) 削除する数
keyに対する特定の要素を削除する。keyが存在しない場合、空の集合とみなし、0が返却される。
keyに保存されている値が集合出ない場合エラーを返す

(railsのラッパーでは、一つずつしか削除できない)

### 戻り値
INTEGER:削除された要素数を返す
(railsのラッパーを通すとtrue,falseで返る)

### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["1", "2", "3", "4", "5"]
pry(main)> Redis.current.srem('a', 1)
=> true
pry(main)> Redis.current.smembers('a')
=> ["2", "3", "4", "5"]
pry(main)> Redis.current.smembers('owata')
=> []
pry(main)> Redis.current.srem('owata', 1)
=> false
pry(main)> Redis.current.srem('a', '2', '3')
ArgumentError: wrong number of arguments (3 for 2)
from /vagrant/www/job-medley/vendor/bundle/ruby/2.2.0/gems/redis-3.2.1/lib/redis.rb:1252:in `srem'
```

## [SUNION(指定要素の結合)](http://redis.io/commands/sunion)
計算量：O(N) Nは与えられた数
与えられたkeyに対する要素を一意な形で結合する

keyが存在しない場合は空のデータとして扱われる

### 戻り値
Array:結合されたデータ


### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["2", "3", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3", "4"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sunion('a','b','c')
=> ["1", "2", "3", "4", "5"]
```

## [SUNIONSTORE(指定要素の結合保存)](http://redis.io/commands/sunionstore)
計算量：O(N) Nは与えられた数
要素を一意な形で結合したものを、改なkeyに保存

keyが既に存在する場合は上書きする

### 戻り値
INTEGER：結合された要素の数


### 使用例
```
pry(main)> Redis.current.smembers('a')
=> ["2", "3", "4", "5"]
pry(main)> Redis.current.smembers('b')
=> ["1", "3", "4"]
pry(main)> Redis.current.smembers('c')
=> ["1", "4"]
pry(main)> Redis.current.sunionstore('abc', 'a','b','c')
=> 5
[128] pry(main)> Redis.current.smembers('abc')
=> ["1", "2", "3", "4", "5"]
```


## [SSCAN(keyをiterateする)](http://redis.io/commands/sscan)
集合状のデータが保存されてるkeyに対し繰り返し処理を行う
railsのラッパー上では使えない（？）っぽい


# 備考
以上なにか間違い等ありましたら、ご指摘いただけたら幸いですm(_ _)m