Redisで複数キーを操作する

# Redis Databaseについて
そもそもRedisデータベースとは？という人のために軽く紹介します。
Redisは[In memory database(インメモリデータベース)](http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9)の１つで、簡単にいえばマシンのメモリ上にデータベースを構築して、読み書きを早く行うデータベースです。

ディスク上のファイルに読み書きを行うよりも高速に行うことが出来ます。

メモリ上にデータベースを構築するので、マシンがダウンすると使えなくなりますが、Redisの場合はメモリに書き込むのと同時に、ファイルに書き込みを行うオプションもあります。

Redisは、Key-valueストア型のデータベースです。
つまり１つのキーに対して、１つのValueとして保存されます。
JavaScriptで言えば１つの大きなJsonObect、Javaで言えばHashMap、Objective-Cで言えばNSMutableDictionaryみたいなものです。

興味のある方は、こちらの紹介記事をお勧めします。
- [Redis勉強会資料](http://www.slideshare.net/yujiotani16/redis-26851700)

# Redis最高！？　-> NO!

Redisはインメモリデータベースだから、高速でいいじゃん！最高！
って訳でもないです。

メモリ上にデータベースを構築するので限界はあります。
Key-valueストア型なので、MySQLみたいに条件検索をしたい場合には向きません。
逆に1ユーザごとにデータを保存する、みたいな場合には向いています。
なのでキャッシュDB的に使いたいようなときには簡単に使えていいでしょう。

# KVSだから・・・
Key-Valueストア型DBなので、当然といえば当然ですが、１つのキーに対して１つの値が基本です。
RedisではHash型の値の保存ができるので、１つのキーに対して１つのHashを割り当て、Hashの中にフィールドを複数作って、複数の値を保存することができます。

これはこれで便利なのですが、面倒なのが、複数のキーを操作しなければならない時です。
Redisは標準でデータベースを操作するためのコマンドを用意しています。
でもKey-Valueストア型DBなので、**1つのコマンドで1つのキーに対して操作することしかできない**のです。

例えば「複数のキーをまとめて削除したいな〜」と思ったら、`DEL`コマンドを複数回実行するか、ワイルドカード(*)を使ってまとめてキーを削除するか、のどちらかです。

例えば、こんなデータがあった場合

```bash
$ redis-cli
keys key:*
1) "key:01"
2) "key:02"
3) "key:03"
4) "key:04"
5) "key:05"
```

巷ではxargs を使ってやっているみたいです。

```bash
$ redis-cli --raw -n 0 KEYS "key:*" | xargs redis-cli -n 0 DEL
(integer) 5
```

でも使いにくくないですか？
こんな単純なデータなら`xargs`でもいいですけど、もっと複雑なキーの組み合わせの場合は、自分でプログラムを書いて、該当するキーだけを抽出して削除、みたいなことをしなければならないわけです。

というか、私も何度もしました。

# redis-ex-cliで複数キーをまとめて操作！

何度も何度も似たようなコードを書いている内に、「これ、コマンドでできたらいいのに・・・」と思って作ったオレオレコマンドが、[redis-ex-cli](https://github.com/wf9a5m75/redis-ex-cli)です。

使い方はこんな感じ。

```bash
// redis-ex-cliコマンドに入る
$> redis-ex-cli

// サーバーに接続
(disconnect) >> server localhost

// データベースのインデックスを選択(デフォルト:0)
localhost >> select 1

// キーの一覧を確認する
localhost >> keys logs:2014:11*
logs:2014:1120:12-40-00
logs:2014:1120:23-04-38
logs:2014:1121:10-42-31
logs:2014:1121:10-42-34
logs:2014:1121:10-42-35

// 11/21のデータだけまとめて削除
localhost >> keys del logs:2014:1121:*
[del]logs:2014:1121:10-42-31
[del]logs:2014:1121:10-42-34
[del]logs:2014:1121:10-42-35

Do you want to delete [N]/Y Y  <!-- いきなり削除しない！　ちゃんと確認できる
```

# 正規表現を使ってキーを絞り込み！
このredis-ex-cliのいいところは、**キーの検索を正規表現を使ってできる**、ということ。
仕組みは単純で、ワイルドカードを使って複数キーを抽出して、そこから正規表現を使って該当するキーを抽出して処理する、ってわけです。

例えば「17時と18時のログデータだけ抽出したい」という場合、正規表現で `/1[7-8]/`でいいので、下のような感じでできます。

```bash
localhost >> keys logs:2015:0404:1[7-8].*
logs:2015:0404:17-40-42
logs:2015:0404:17-41-55
logs:2015:0404:17-56-05
logs:2015:0404:18-01-36
logs:2015:0404:18-06-26
logs:2015:0404:18-11-17
```

Redis標準のコマンドだと、2回実行しないと出来ません。

```bash
redis 127.0.0.1:6379 > keys logs:2015:0404:17*
logs:2015:0404:17-40-42
logs:2015:0404:17-41-55
logs:2015:0404:17-56-05

redis 127.0.0.1:6379 > keys logs:2015:0404:18*
logs:2015:0404:18-01-36
logs:2015:0404:18-06-26
logs:2015:0404:18-11-17
```

# 複数キーをまとめてコピー

Redisは高速なので、ちょっとした処理をするときに作業用DBみたいな扱いで使うことがあります。
その場合、元データをいきなり操作しないですよね（普通は）。
だから複数キーのコピーを作りたいことが頻繁にあります。

redis-ex-cliなら簡単です。`keys copy`を使って、いい感じにコピーしてくれます。

```bash
localhost >> keys copy logs:2015:04* logs:test:

[copy]logs:2015:0401:06-59-46 --> logs:test:01:06-59-46
[copy]logs:2015:0406:07-09-22 --> logs:test:06:07-09-22
[copy]logs:2015:0401:07-11-43 --> logs:test:01:07-11-43
[copy]logs:2015:0401:07-12-36 --> logs:test:01:07-12-36

Do you want to copy [N]/Y Y
```

# 複数キーをまとめて変更？　余裕です
正規表現のgroupingを使って置き換えもできます。

```bash
localhost >> keys rename logs:2014:04(.*) logs:2015:05$1:test

[rename]logs:2014:0401:06-59-46 --> logs:2015:0501:06-59-46:test
[rename]logs:2014:0401:07-11-43 --> logs:2015:0501:07-11-43:test
[rename]logs:2014:0401:07-12-36 --> logs:2015:0501:07-12-36:test

Do you want to rename [N]/Y 
```

# Hash型の1フィールドだけまとめて変更したい
テストフラグとか付けたい時ありませんか？
redis-ex-cliなら、`hset`コマンドをまとめて実行します。

```bash
localhost >>keys hset logs:2015:04* isTest true

[hset]logs:2015:0401:06-59-46
[hset]logs:2015:0401:07-01-02
[hset]logs:2015:0401:07-11-43
[hset]logs:2015:0401:07-12-36

Do you want to set values [N]/Y 
```

# Hash型の1フィールドだけまとめて削除したい
1フィールドだけ削除したいのですか？ `hdel`を使ってください。

```bash
localhost >>keys hdel logs:* isTest

[hdel]logs:2015:0401:06-59-46
[hdel]logs:2015:0401:07-01-02
[hdel]logs:2015:0401:07-11-43
[hdel]logs:2015:0401:07-12-36

Do you want to delete [N]/Y 
```

# あるフィールドで特定の値を持つキーだけを抽出したい

欲張りですね。でもできます。今のところ検索だけできます。

```bash
localhost >>keys hsearch logs:2015:04* sendto ^310\-.*

logs:2015:0401:13-45-17
logs:2015:0401:15-02-59
logs:2015:0402:14-09-03
logs:2015:0404:15-20-56
logs:2015:0404:17-41-55
logs:2015:0404:17-56-05
logs:2015:0405:11-32-43
logs:2015:0405:14-50-55
logs:2015:0405:14-54-07
```

# バックアップを取りたい
操作をする前にデータのバックアップを行う。そうですよね、したいですよね。
データを再現するRedisのコマンド形式でファイルに保存します。

```bash
localhost >> keys export logs:2015:0404:1[7-8].* 20150404-from17to18.log
```


# バックアップから復元する
`key export`で作成したバックアップからデータを復元するなら、`key import :filename`で指定するだけです。

```bash
localhost >> keys import 20150404-from17to18.log
```

#使いたくなってきましたか？
使うためには、Node.jsをあなたのPCにインストールしてください。
つぎに下記コマンドを実行するだけです。

```bash
$> (sudo) npm -g install redis-ex-cli
```

あとは　[https://github.com/wf9a5m75/redis-ex-cli](https://github.com/wf9a5m75/redis-ex-cli)　を読んでください。