DB以外でDBIx::Skinny::Iteratorを使う #15B!

こんにちわ!nekokakです!

十伍日目はDBIx::SkinnyでDB意外のデータを使う方法についてです。

DBIx::SkinnyはDBIxとついているように、DBIを拡張するモジュールです。

しかし、データのイテレーションはDBのデータ意外でも使いたい場合があると思います。

そこで、今日は、DBのデータ意外でのIteratorの使い方についてです。

と、その前に、DBIx::Skinny::Iteratorの使い方をざっくり説明しましょう。

DBIx::Skinny::IteratorはDB検索結果のレコードを取りまとめるオブジェクトとなります。

複数のレコードを取りまとめて、データをイテレーションさせるためのクラスです。

itaratorではnext/first/reset/count/allというメソッドがあります。

nextメソッドを使うと、1行ずつデータを取得して、処理を行うことができます。

my $itr = $db->search('user');
while (my $row = $itr->next) {
    # some process....
}

allメソッドを使うと、一気に配列に行データを格納することができます。

my $itr = $db->search('user');
my @users = $itr->all;

firstメソッドを使うと、イテレータから1行だけデータを取得することができます。

my $itr = $db->search('user');
my $user = $itr->first;

countメソッドを使うと、現在イテレータが保持しているデータのレコード数を取得することができます。

my $itr = $db->search('user');
my $count = $itr->count;

resetメソッドを使うと、途中まで進めたイテレータのポジションをはじめに戻すことができます。

下の例の場合、resetメソッドを呼び出さないと、allメソッドでは2行目以降のデータしか取得できません。

my $itr = $db->search('user');
# 1行目を取得(イテレータのポジションが一個進む)
my $user = $itr->first;
# イテレータのポジションをリセットする
$itr->reset;
# 全行を取得する
my @users = $itr->all;

no_cacheメソッドというのがgithubの最新バージョンに存在します。

これはDBIx::Skinny::IteratorがDBから取り出した行データをインスタンスにキャッシュしているのをやめるものです。

resetメソッドを組み合わせて、同じSQLの実行結果を使いまわす場合は、

インスタンスにキャッシュされたデータをつかいまわすと、DBに余計なクエリを発行擦る必要がなく、

負荷軽減になるのですが、同じSQLの実行結果を使いまわさない場合で、

1クエリで大量のレコードが取得される場合、インスタンスにキャッシュしてしまうと

メモリの無駄遣いになるので、そういった場合に使用します。

my $itr = $db->search('user');
# itratorインスタンスにrowデータをキャッシュしないことを指示
$itr->no_cache;
my @users = $itr->all;

DBIx::Skinny::Itaratorの使い方としてはこんな感じです。

DBIx::Classを普段使っている人は特に違和感なく使えると思います。

さて、本日の本題である、DB意外のデータをDBIx::Skinny::Itaratorで扱う方法ですが、

例えば、

my @users = (
    {name => 'nekokak'},
    {name => 'yappo'},
    {name => 'nekoya'},
);
my $itr = Proj::DB->data2itr('user', \@users);
while (my $row = $itr->next) {
    warn $row->name;
}

このような使い方が可能です。

data2itrメソッドを使うと、ある、hashrefが格納されてるarrayrefをわたすと、

DBIx::Skinny::Iteratorのオブジェクトにしてくれます。

#14で説明した、memcachedから取得したデータをitaratorに戻すのと同じです。

itaratorに戻した後に取得される1データはDBIx::SkinnyのRowクラスでオブジェクト化されていますので、

あたかもDBから取得したデータのように扱うことが可能です。

本題がめっちゃ短いですが、simple is bestということで。

明日はDBIx::Skinnyを使った場合のdb shardingについて書いてみようかと思います。

have a nice skinny days!:)