RedisのCRUD操作をPythonから行う

※自分の勉強メモ用記事

# はじめに
- RedisのCRUD操作をPythonから行う
    - Pythonクライアントは [redis-py](https://github.com/andymccurdy/redis-py) を利用
- Document
    - [Welcome to redis-py’s documentation!](https://redis-py.readthedocs.io)
        - ライブラリドキュメント
    - [The full list of commands](https://redis.io/commands) 
        - Redis-cliのコマンドリファレンス


# 環境構築
## Dockerを利用

```docker
docker run --name some-redis -d --rm -p 6379:6379 redis:5.0.0
```
## Pythonクライアントのインストール
```python

# condaでインストール
conda install redis
# pipでインストール
pip install redis
```
- [redis-py Document](https://redis-py.readthedocs.io/en/latest/)
    - ライブラリドキュメント
- [The full list of commands](https://redis.io/commands)
    - redis-cliコマンド



# 基本概念
- KeyValue
- 永続化可（制約多し）
- 代表的なデータ形式([詳細](https://redis.io/topics/data-types-intro))
    - Strings
    - Lists
    - Sets
    - Hashes
    - etc
- PubSub可
- マネージド有
    - [CLOUD MEMORYSTORE](https://cloud.google.com/memorystore/)
    - [Amazon ElastiCache](https://aws.amazon.com/jp/elasticache/)

# CRUD操作

## ライブラリ読込/接続

```python

import redis

# 接続
r = redis.StrictRedis(host='yourhost', port=6379, db=0)
```
※コネクションプール使うと2倍速らしい

## Strings
- 単純なKeyValue

![image.png](https://qiita-image-store.s3.amazonaws.com/0/379310/eac84345-7f35-2c8c-d8b0-c283fcb2806c.png)

### Create

```python
# Keyに対してValueを追加
r.set('Key01', 'Value01')
r.set('Key02', 'Value02')
```
### Read

```python
# Key01のValueを読み出す
r.get('Key01')
```
### Update

```python
# Keyを指定してValueを更新
r.set('Key02', 'Value02_upd')
```

### Delete

```python
# Keyの削除
r.delete('Key01','Key02')
``` 

## Lists

- Keyに対して配列を格納する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/379310/57256576-8b8a-9e82-2124-49bb4ae30722.png)

### Create

```python
# KeyList01というKeyに対してリスト作成 > [Value01]
r.rpush('KeyLists01', 'Value01')

# Key01リスト右側にValueを追加 > [Value01,Value02,Value03]
r.rpush('KeyLists01', 'Value02')
r.rpush('KeyLists01', 'Value03')

# Key01リスト左側にValueを追加 > [Value00,Value01,Value02,Value03]
r.lpush('KeyLists01','Value00')

# ループでValueを追加
for i in ['A','B','C','D','E']:
    r.rpush('KeyLists01','Value' + i)
```
### Read

```python
# 左から範囲指定しValueを表示
# lrange(Key,Start,End) ※Endは含まれる
r.lrange('KeyLists01',0,r.llen('Key01')) 
```

### Update
```python
# KeyとindexでValueを更新する
r.lset('KeyLists01',1,'Value01_upd')
```
### Delete

```python
# 右から1要素削除し、削除対象のValueを戻り値とする
pop = r.rpop('KeyLists01')
print(pop) # > ValueE

# 左から1要素削除
pop = r.lpop('KeyLists01')
print(pop) # > Value00
```

## Sets

- Keyに対して集合を格納する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/379310/bc56ae21-92de-9cd6-e27d-2dacce4177b9.png)

### Create/Update

```python
# 1番目の引数にKeyを指定し、2番目以降にMemberを指定
r.sadd('KeySets01', 'A','B','C','D')
r.sadd('KeySets01', 'D') # 重複なので追加されない（戻り値 0）
r.sadd('KeySets01', 'E') # 追加される（戻り値 1）
```

### Read

```python
# Key内のMemberを確認
r.smembers('KeySets01')
```

### Delete

```python
# KeyとMemberで削除
r.srem('KeySets01','A')
```

### Calculate

```python
# 計算用データ登録
r.sadd('KeySets02','C','D','E','F')
# 和集合
r.sunion('KeySets01','KeySets02')
# 積集合
r.sinter('KeySets01','KeySets02')
# 差集合
r.sdiff('KeySets01','KeySets02')
```

## Hashes

- Keyに対してFieldとValueを格納する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/379310/e6f6dcad-f447-86cf-c6b5-95ba1d248804.png)

### Create

```python
# Key,Field,Valueの3構造のデータ
r.hset("lv0", "lv1_1", "lv2_1")
r.hset("lv0", "lv1_2", "lv2_2")
r.hset("lv0", "lv1_3", "lv2_3")
r.hset("lv0", "lv1_4", "lv2_4")
```

### Read
```python
# Key,Fieldを指定してValueを取得する
r.hget('lv0', 'lv1_3')

# Keyでデータを取得する
r.hgetall("lv0")
```

### Update
```python
# Key,Fieldを指定してValueを更新
r.hset("lv0", "lv1_3", "update_lv2_3")
# r.hget('lv0', 'lv1_3') > b'update_lv2_3'
```

### Delete
```python
# Key,Fieldで削除
r.hdel('lv0','lv1_3')
```
## OTHER

### DROP

```python
# CurrentDBの全てのキーを削除
r.flushdb()
# 全てのDBの全てのキーを削除
r.flushall()
```

### Keys
```python
# どのデータ型でもKeyで削除できる
r.delete(Key)

# Key一覧
r.keys()

# Keyに格納されたデータ型表示
r.type(Key)

# Keyに格納されたデータ型表示全量
for i in r.keys():
    print(i,r.type(i))
```