Symfoware

Symfowareについての考察blog

Redis + FuelPHP 1.8でリストをソートして取得する(sort)

FuelPHPでRedisに接続してみました。
FuelPHP 1.8 Redisに接続してデータの登録、取得、削除
Redis + FuelPHP 1.8でリストの操作(rpush, lrange, ltrim)

今回は、登録したリスト形式のデータをソートして取得してみます。
Redis Command - SORT(指定したキーのリストをソート)


簡単なサンプル



文字列データを登録。
ソート済の状態で取得してみます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // 一旦クリア
  11.         $redis->del('key');
  12.         $values = [];
  13.         foreach(range(1, 20) as $i) {
  14.             $values[] = sprintf('%03d-value', $i);
  15.         }
  16.         // データの複数登録
  17.         $redis->rpush('key', ...$values);
  18.         // データの取得
  19.         $items = $redis->sort('key', 'alpha', 'desc');
  20.         foreach($items as $item) {
  21.             echo($item . PHP_EOL);
  22.         }
  23.         $redis->del('key');
  24.     }
  25. }



実行結果


$ oil r sample
020-value
019-value
018-value
017-value
016-value
015-value
014-value
013-value
012-value
011-value
010-value
009-value
008-value
007-value
006-value
005-value
004-value
003-value
002-value
001-value



文字列をソートする場合は「alpha」を指定する必要があります。




取得件数指定



「limit」でデータの取得件数を指定できます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // 一旦クリア
  11.         $redis->del('key');
  12.         $values = [];
  13.         foreach(range(1, 20) as $i) {
  14.             $values[] = sprintf('%03d-value', $i);
  15.         }
  16.         // データの複数登録
  17.         $redis->rpush('key', ...$values);
  18.         // データの取得
  19.         $items = $redis->sort('key', 'alpha', 'limit', 0, 10, 'desc');
  20.         foreach($items as $item) {
  21.             echo($item . PHP_EOL);
  22.         }
  23.         $redis->del('key');
  24.     }
  25. }



実行結果


$ oil r sample
020-value
019-value
018-value
017-value
016-value
015-value
014-value
013-value
012-value
011-value






store



コマンドの最後に「store [キー]」を指定すると、取得した結果が新しいキー名の値として設定されます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // 一旦クリア
  11.         $redis->del('key');
  12.         $redis->del('new_key');
  13.         $values = [];
  14.         foreach(range(1, 20) as $i) {
  15.             $values[] = sprintf('%03d-value', $i);
  16.         }
  17.         // データの複数登録
  18.         $redis->rpush('key', ...$values);
  19.         // ソート結果を「new_key」に保存
  20.         $redis->sort('key', 'alpha', 'limit', 0, 10, 'desc', 'store', 'new_key');
  21.         // データの取得
  22.         $items = $redis->lrange('new_key', 0, -1);
  23.         foreach($items as $item) {
  24.             echo($item . PHP_EOL);
  25.         }
  26.         $redis->del('key');
  27.         $redis->del('new_key');
  28.     }
  29. }



実行結果


$ oil r sample
020-value
019-value
018-value
017-value
016-value
015-value
014-value
013-value
012-value
011-value




キーは同じ名称を指定して上書きすることも可能です。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // 一旦クリア
  11.         $redis->del('key');
  12.         $values = [];
  13.         foreach(range(1, 20) as $i) {
  14.             $values[] = sprintf('%03d-value', $i);
  15.         }
  16.         // データの複数登録
  17.         $redis->rpush('key', ...$values);
  18.         // ソート結果を「key」に保存
  19.         $redis->sort('key', 'alpha', 'limit', 0, 10, 'desc', 'store', 'key');
  20.         // データの取得
  21.         $items = $redis->lrange('key', 0, -1);
  22.         foreach($items as $item) {
  23.             echo($item . PHP_EOL);
  24.         }
  25.         $redis->del('key');
  26.     }
  27. }



実行結果


$ oil r sample
020-value
019-value
018-value
017-value
016-value
015-value
014-value
013-value
012-value
011-value





テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/06/26(火) 23:45:05|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redis + FuelPHP 1.8でリストの操作(rpush, lrange, ltrim)

FuelPHPからRedisに接続してみました。
FuelPHP 1.8 Redisに接続してデータの登録、取得、削除

Pythonで試したのと同様の操作を行ってみます。
Redis リストデータの操作について(rpush, lrange, ltrim)


rpushとlrange



rpushでリストにデータ登録。
lrangeで登録したデータを取得してみます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // データの登録
  11.         foreach(range(1, 20) as $i) {
  12.             $redis->rpush('key', 'value-' . $i);
  13.         }
  14.         // データの取得
  15.         foreach($redis->lrange('key', 0, 10) as $item) {
  16.             echo($item . PHP_EOL);
  17.         }
  18.         // キーを削除
  19.         $redis->del('key');
  20.     }
  21. }



狙い通りの実行結果が得られました。


$ oil r sample
value-1
value-2
value-3
value-4
value-5
value-6
value-7
value-8
value-9
value-10
value-11






rpushで一括登録



Pythonで試したときと同様、rpushは第二引数以降をリストとして追加します。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // データの複数登録
  11.         $redis->rpush('key', 'value-1', 'value-2', 'value-3', 'value-4', 'value-5');
  12.         // データの取得
  13.         foreach($redis->lrange('key', 0, 10) as $item) {
  14.             echo($item . PHP_EOL);
  15.         }
  16.         // キーを削除
  17.         $redis->del('key');
  18.     }
  19. }



実行結果


$ oil r sample
value-1
value-2
value-3
value-4
value-5




そのため、最初のプログラムは以下のように書き換えられます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         $values = [];
  11.         foreach(range(1, 20) as $i) {
  12.             $values[] = 'value-' . $i;
  13.         }
  14.         // データの複数登録
  15.         $redis->rpush('key', ...$values);
  16.         // データの取得
  17.         foreach($redis->lrange('key', 0, 10) as $item) {
  18.             echo($item . PHP_EOL);
  19.         }
  20.         // キーを削除
  21.         $redis->del('key');
  22.     }
  23. }






キーの削除(ltrim)



最後に、ltrimで読み込んだリストを削除してやります。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         $values = [];
  11.         foreach(range(1, 20) as $i) {
  12.             $values[] = 'value-' . $i;
  13.         }
  14.         // データの複数登録
  15.         $redis->rpush('key', ...$values);
  16.         // データの取得
  17.         while(true) {
  18.             $items = $redis->lrange('key', 0, 10);
  19.             if (empty($items)) {
  20.                 break;
  21.             }
  22.             
  23.             foreach($items as $item) {
  24.                 echo($item . PHP_EOL);
  25.             }
  26.             $redis->ltrim('key', count($items), -1);
  27.         }
  28.     }
  29. }



実行結果


$ oil r sample
value-1
value-2
value-3
value-4
value-5
value-6
value-7
value-8
value-9
value-10
value-11
value-12
value-13
value-14
value-15
value-16
value-17
value-18
value-19
value-20





【参考URL】

【PHP】受け取った可変長引数を別の関数に可変長引数として渡す

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/06/26(火) 22:53:46|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

FuelPHP 1.8 Redisに接続してデータの登録、取得、削除

FuelPHP 1.8でRedisに接続してデータを操作してみます。

設定ファイル



Redisに接続するため、db.phpに接続設定を記載。

・fuel/app/config/[development]/db.php


  1. <?php
  2. /**
  3. * The development database settings. These get merged with the global settings.
  4. */
  5. return array(
  6.     'default' => array(
  7.         'connection' => array(
  8.             'dsn'        => 'mysql:host=localhost;dbname=fuel_dev',
  9.             'username' => 'root',
  10.             'password' => 'root',
  11.         ),
  12.     ),
  13. // ここから
  14.     'redis' => array(
  15.         'default' => array(
  16.             'hostname' => '192.168.1.102',
  17.             'port' => 6379,
  18.             'timeout' => null,
  19.         ),
  20.     ),
  21. // ここまで
  22. );





oil task



コマンドで実行するため、タスクとしてプログラムを記載しました。

・fuel/app/task/sample.php


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         // データの登録と取得
  11.         $redis->set('key', 'value');
  12.         echo($redis->get('key') . PHP_EOL);
  13.         // データの削除
  14.         $redis->del('key');
  15.         echo($redis->get('key') . PHP_EOL);
  16.     }
  17. }



oilコマンドで実行してみます。


$ oil r sample
value
(空白)



あっさり接続できました。



データベースの切り替え



redisはselectでデータベースを切り替えることができます。
Redis Command - SELECT(データベースの切り替え)

簡単にテストしてみます。


  1. <?php
  2. namespace Fuel\Tasks;
  3. class Sample
  4. {
  5.     public static function run()
  6.     {
  7.         // redisに接続
  8.         $redis = \Redis_Db::forge();
  9.         
  10.         $redis->select(0);
  11.         // データの登録と取得
  12.         $redis->set('key', 'value-0');
  13.         echo($redis->get('key') . PHP_EOL);
  14.         $redis->select(1);
  15.         // データの登録と取得
  16.         $redis->set('key', 'value-1');
  17.         echo($redis->get('key') . PHP_EOL);
  18.         $redis->select(0);
  19.         // データの削除
  20.         $redis->del('key');
  21.         echo($redis->get('key') . PHP_EOL);
  22.         $redis->select(1);
  23.         // データの登録と取得
  24.         echo($redis->get('key') . PHP_EOL);
  25.         $redis->del('key');
  26.     }
  27. }



実行結果


$ oil r sample
value-0
value-1
(空白)
value-1



ちゃんと動いてくれているようですね。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/06/26(火) 22:33:36|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redis 1つのリストに登録できるデータ件数について

Redisのリストを一時キャッシュとして使ってみようと思います。
Redis リストデータの操作について(rpush, lrange, ltrim)

ふと、1つのリストにどの程度の件数登録できるか気になったので試してみます。


郵便番号データ



適当な大量データがなかったので、郵便番号と住所を使用することにしました。
読み仮名データの促音・拗音を小書きで表記するもの(zip形式)

1つのリストに

[郵便番号]:[住所]


という形式で登録してみます。


  1. # -*- coding:utf-8 -*-
  2. import codecs
  3. import redis
  4. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  5. with codecs.open('KEN_ALL.CSV', 'r', 'ms932') as f:
  6.     values = []
  7.     for line in f:
  8.         data = line.split(',')
  9.         zipcode = data[2].strip('"')
  10.         address = ''.join([s.strip('"') for s in data[6:9]])
  11.         values.append('%s:%s' % (zipcode, address))
  12.         
  13.         if len(values) == 100:
  14.             r.rpush('key', *values)
  15.             values = []
  16.             
  17.     if values:
  18.         r.rpush('key', *values)



実行すると、普通に登録が完了しました。

llenでリストの件数を取得してみます。
Redis Command - LLEN(リストの要素数を取得)


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  4. print(r.llen('key'))



実行結果


$ python3 sample.py
124189



約12万件。全県登録できていますね。

ファイルに復元してデータを確認してみます。
データはバイトで登録されているので、decodeで文字列に戻してやります。


  1. # -*- coding:utf-8 -*-
  2. import codecs
  3. import redis
  4. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  5. with codecs.open('result.txt', 'w', 'utf-8') as f:
  6.     while True:
  7.         items = r.lrange('key', 0, 100)
  8.         if not items:
  9.             break
  10.         for item in items:
  11.             f.write('%s\n' % item.decode())
  12.         r.ltrim('key', len(items), -1)



バッチリ復元されました。



1アイテムのデータ容量を増加



リストの1項目の長さを約10倍にして登録してみます。


  1. # -*- coding:utf-8 -*-
  2. import codecs
  3. import redis
  4. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  5. with codecs.open('KEN_ALL.CSV', 'r', 'ms932') as f:
  6.     values = []
  7.     for line in f:
  8.         data = line.split(',')
  9.         zipcode = data[2].strip('"')
  10.         address = ''.join([s.strip('"') for s in data[6:9]])
  11.         # 住所の長さを10倍にする
  12.         values.append('%s:%s' % (zipcode, address * 10))
  13.         
  14.         if len(values) == 100:
  15.             r.rpush('key', *values)
  16.             values = []
  17.             
  18.     if values:
  19.         r.rpush('key', *values)



データを復元


  1. # -*- coding:utf-8 -*-
  2. import codecs
  3. import redis
  4. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  5. with codecs.open('result.txt', 'w', 'utf-8') as f:
  6.     while True:
  7.         items = r.lrange('key', 0, 100)
  8.         if not items:
  9.             break
  10.         for item in items:
  11.             f.write('%s\n' % item.decode())
  12.         r.ltrim('key', len(items), -1)



復元したファイルの容量は約44MBになりましたが、全く問題ありませんでした。
安心してキャッシュ領域に使えそうです。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/06/26(火) 21:59:41|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redis リストデータの操作について(rpush, lrange, ltrim)

Redisサーバーを一時的なキャッシュ領域として使いたい場合があります。
受け取ったデータをとりあえずリストに追加。
バックグラウンドでリストからまとめて10件程取得して処理するパターンを考えてみました。

redis-py



今回はPython(redis-py)で試してみます。
Python3からRedis Server 4へ接続する(redis-py使用)

rpushでリストの末尾にデータを登録
Redis Command - RPUSH(リストの末尾にデータを追加)

lrangeで登録したデータを取り出してみます。
Redis Command - LRANGE(リストの値を取得)


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  4. for i in range(1, 21):
  5.     r.rpush('key', 'value-%d' % i)
  6. result = r.lrange('key', 0, 10)
  7. for r in result:
  8.     print(r)



狙い通りの実行結果になりました。


$ python3 sample.py
b'value-1'
b'value-2'
b'value-3'
b'value-4'
b'value-5'
b'value-6'
b'value-7'
b'value-8'
b'value-9'
b'value-10'
b'value-11'





rpushで一括登録



rpushは第二引数以降に登録するデータを複数指定できます。


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  4. r.rpush('key', 'value-1', 'value-2', 'value-3', 'value-4')
  5. result = r.lrange('key', 0, 10)
  6. for r in result:
  7.     print(r)



実行結果


$ python3 sample.py
b'value-1'
b'value-2'
b'value-3'
b'value-4'



それなので、最初のコードは以下のように書き換えることができます。


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  4. values = ['value-%d' % i for i in range(1, 21)]
  5. r.rpush('key', *values)
  6. items = r.lrange('key', 0, 10)
  7. for item in items:
  8.     print(item)





キーの削除(ltrim)



取り出したリストの値をまとめて削除するには、ltrimを使用します。
Redis Command - LTRIM(指定した範囲以外の値を削除)

これらを踏まえ、登録したリストから値を取得。
取得済の値を削除しつつ、次の値を取得するプログラムはこうなりました。


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. r = redis.StrictRedis(host='192.168.1.102', port=6379, db=0)
  4. values = ['value-%d' % i for i in range(1, 21)]
  5. r.rpush('key', *values)
  6. while True:
  7.     items = r.lrange('key', 0, 10)
  8.     if not items:
  9.         break
  10.     for item in items:
  11.         print(item)
  12.     
  13.     print('-' * 10)
  14.     r.ltrim('key', len(items), -1)



実行結果


$ python3 sample.py
b'value-1'
b'value-2'
b'value-3'
b'value-4'
b'value-5'
b'value-6'
b'value-7'
b'value-8'
b'value-9'
b'value-10'
b'value-11'
----------
b'value-12'
b'value-13'
b'value-14'
b'value-15'
b'value-16'
b'value-17'
b'value-18'
b'value-19'
b'value-20'
----------



いい感じです。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/06/26(火) 21:36:45|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ