かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JavaScript (node.js) ioredis 使ってみたのメモ

Redis との接続

const Redis = require('ioredis');
const redis = new Redis();
// docker などで動かしている場合は port host を指定する
const redis = new Redis(6379, 'redis');
// 使用する db を指定する場合は、 オプションを使用
const redis = new Redis(6379, 6379, {db: 1});

String 型

// set
redis.set('cute', '星宮いちご'); // => 'OK'

// get
redis.get('cute'); // => '星宮いちご'
redis.get('cool'); // => null

// delete
redis.del('cute'); // => 削除できた場合は1, keyが無かった場合は0

// 期限付きでset 期限は秒で指定
redis.set('cool', '霧矢あおい', 'EX', 60); // => 'OK'

// 複数の値を作成
redis.set(cute', '星宮いちご', 'cool', '霧矢あおい', '...');
// => syntax error (redis のコマンド的な書き方はできない)
// 👇
// multi, pipeline を使う
redis
  .multi()
  .set('cute', '星宮いちご', 'EX', 60)
  .set('cool', '霧矢あおい', 'EX', 60)
  .set('sexy', '紫吹蘭', 'EX', 60)
  .exec(); // => [ [ null, 'OK' ], [ null, 'OK' ], [ null, 'OK' ] ]

// 複数の値を削除
redis.del('cute', 'cool', 'sexy'); // => 3 削除に成功した数が帰る

同じ key に set した場合値は上書きされる
.multi(), pipeline() で複数の処理をした場合、exec() が実行された時に実際に redis に登録されるので、有効期限など同じにすることができるっぽい。

If you want to send a batch of commands (e.g. > 5), you can use pipelining to queue the commands in memory and then send them to Redis all at once. This way the performance improves by 50%~300%
redis.pipeline() creates a Pipeline instance. You can call any Redis commands on it just like the Redis instance. The commands are queued in memory and flushed to Redis by calling the exec method
cf GitHub - luin/ioredis: 🚀 A robust, performance-focused and full-featured Redis client for Node.js.

List 型

// リスト型を作成して値を追加
// key, value, value, value, … で作成
redis.rpush('solie', '星宮いちご', '霧矢あおい', '紫吹蘭'); // 3 リストの要素数が返る

// リストの内容を全取得
redis.lrange('solie', 0, -1);
// => [ '星宮いちご', '霧矢あおい', '紫吹蘭' ]

// get は使えない
redis.get('solie'); // => syntax error

// index の値を取得
redis.lindex('solie', 2); // => '紫吹蘭'

// リストの先頭を取り出して削除
redis.lpop('solie'); // => '星宮いちご'

// リストの最後を取り出して削除
redis.rpop('solie'); // => '紫吹蘭'

// リストの先頭に追加する
redis.lpush('tristar', '神崎美月', '藤堂ユリカ', '紫吹蘭');
// => tristar: ['紫吹蘭', '藤堂ユリカ', '神崎美月']

// index の値を置き換え
redis.lpush('tristar', 0, '一ノ瀬かえで');
// => tristar: [ '一ノ瀬かえで', '藤堂ユリカ', '神崎美月' ]

// リストから指定した value の要素を削除
redis.lrem('tristar', 0, '神崎美月');
// => tristar: [ '一ノ瀬かえで', '藤堂ユリカ' ]

// lrem の第2引数は先頭から削除する要素数を指定できる
redis.rpush('arr', 1, 2, 3, 1, 2, 3, 1, 2, 3);
// 0 の場合は該当する要素全て削除する
redis.lrem('arr', 0, 1);
// => arr: [ '2', '3', '2', '3', '2', '3' ]

// 1 を指定すると最初の1つめの要素だけ削除される
redis.lrem('arr', 1, 2);
// => arr: [ '3', '2', '3', '2', '3' ]

// 2 を指定すると先頭から2つ要素が削除される
redis.lrem('arr', 2, 3);
// => arr: [ '2', '2', '3' ]

// list 型のデータを削除
redis.del('arr');

Hash 型

// ハッシュ型を作成してデータを追加
// key, field, value, field, value … でデータを作成
redis.hset('luminas', 'cute', '大空あかり', 'cool', '氷上すみれ', 'pop', '新条ひなき');

// field の値を取得
redis.hget('luminas', 'cute'); // => '大空あかり'

// field を削除
redis.hdel('luminas', 'cool');
// => luminas: { cute: '大空あかり', pop: '新条ひなき' }

// データまとめて追加
// hmset は追加するデータをオブジェクトで指定できる
redis.hmset('luminas', {'cool': '氷上すみれ', 'sexy': '紅林珠璃'});
// => luminas: { cute: '大空あかり', pop: '新条ひなき', cool: '氷上すみれ', sexy: '紅林珠璃' }

// 複数 field の値をまとめて取得
redis.hmget('luminas', 'pop', 'sexy'); // => [ '新条ひなき', '紅林珠璃' ]

// field を全て取得
redis.hkeys('luminas');
// => [ 'cute', 'pop', 'sexy', 'cool' ]

// value を全て取得
redis.hvalss('luminas');
// => [ '大空あかり', '新条ひなき', '紅林珠璃', '氷上すみれ' ]

// field, value を全て取得
redis.hgetall('luminas');
// => { cute: '大空あかり', pop: '新条ひなき', sexy: '紅林珠璃', cool: '氷上すみれ' }

// hash 型のデータを削除
redis.del('luminas');

ioredishgetall は redis のコマンドとは異なりオブジェクトを返すので map などを使おうとしたらエラーになるので注意が必要

List 型 / Hash 型に有効時間を設定

List 型 / Hash 型の set メソッドには EX キーワードで有効時間を設定できる方法がないので、.pipeline() で繋いで .expire(key, time) で設定する。
pipeline は特に前に操作した key などを保持しているわけではないので、続けて実行する .expire にもキーを指定する必要がある

redis
  .pipeline()
  .rpush('solie', '星宮いちご', '霧矢あおい', '紫吹蘭')
  .expire('solie', 60)
  .exec();
// => [ '星宮いちご', '霧矢あおい', '紫吹蘭' ] ttl: 60

redis
  .pipeline()
  .hset('luminas', 'cute', '大空あかり', 'cool', '氷上すみれ', 'pop', '新条ひなき')
  .expire('luminas', 60)
  .exec();
// => { cute: '大空あかり', cool: '氷上すみれ', pop: '新条ひなき' } ttl: 60

// 有効期限は `ttl(key)` で取得できる
await new Promise((resolve => setTimeout(resolve, 5000))); // 5 秒停止
redis.ttl('solie');
// => 55

 
基本的にはこのくらいのコマンドでそれなりの事ができそうです。 他にも Pub/Sub など色々なことができるみたいなので、必要になったら触ってみたいと思います。


[参考]

いちばん大切なのに誰も教えてくれない段取りの教科書

いちばん大切なのに誰も教えてくれない段取りの教科書

  • 作者:水野 学
  • 発売日: 2018/10/11
  • メディア: 単行本(ソフトカバー)
👆 安定と信頼の水野学さんの本たいへんよかったです。