少し前のブログで、OSSのEmbulkについて書いてみましたが、MysqlからCsvへの変換という無難な内容だったので、今回はあまり使用例がアップされていないプラグインにフォーカスしてみます。
フォーカスするプラグインは、データの変換をRubyのコードで定義できる"embulk-filter-eval"です。
embulk-filter-evalの概要
embulk-filter-evalは"FILTER"に分類されるプラグインで、"INPUT"でデータを読み込んだ後、"OUTPUT"にデータを渡す前に、データに変換処理を加えられます。また、出力するカラムを選択できるので、不要なカラムを切り捨てることもできます。
データの転送に際して、ちょっとしたデータの加工をしたい場合や、決まったフォーマットへの変換処理に使えそうですね。
データの変換内容はRubyのコードで定義できるそうですが、具体的にどんなことができるのか、使ってみて分かったことを書いていきます。
なお、出力カラムの選択に関しては、下記の資料を見ればすぐに分かる設定ですので、今回は特に触れません。
インストール方法、ymlファイルの書式、出力カラムの選択方法などは下記のGitHubにアップされている資料をご参照ください。
https://github.com/mgi166/embulk-filter-eval
embulk-filter-evalの利用例
ここから具体的なデータ変換パターンについて、実際に試してみます。インプットのデータは"embulk example"で作成されるサンプルデータとし、ymlを編集する都度、"embulk preview config.yml"コマンドでどんな変換がされるのか確認していきます。
※どんな変換が行えるかの確認が目的なので、以降の利用例では計算の中身に深い意味は持たせていません
補足として、変換なしの"embulk preview config.yml"の結果は下記の通りです。
以降、embulk-filter-evalによる変換後の出力との比較として参考にしてください。
+---------+--------------+-------------------------+-------------------------+----------------------------+
| id:long | account:long | time:timestamp | purchase:timestamp | comment:string |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| 1 | 32,864 | 2015-01-27 19:23:49 UTC | 2015-01-27 00:00:00 UTC | embulk |
| 2 | 14,824 | 2015-01-27 19:01:23 UTC | 2015-01-27 00:00:00 UTC | embulk jruby |
| 3 | 27,559 | 2015-01-28 02:20:02 UTC | 2015-01-28 00:00:00 UTC | Embulk "csv" parser plugin |
| 4 | 11,270 | 2015-01-29 11:54:36 UTC | 2015-01-29 00:00:00 UTC | NULL |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| id:long | account:long | time:timestamp | purchase:timestamp | comment:string |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| 1 | 32,864 | 2015-01-27 19:23:49 UTC | 2015-01-27 00:00:00 UTC | embulk |
| 2 | 14,824 | 2015-01-27 19:01:23 UTC | 2015-01-27 00:00:00 UTC | embulk jruby |
| 3 | 27,559 | 2015-01-28 02:20:02 UTC | 2015-01-28 00:00:00 UTC | Embulk "csv" parser plugin |
| 4 | 11,270 | 2015-01-29 11:54:36 UTC | 2015-01-29 00:00:00 UTC | NULL |
+---------+--------------+-------------------------+-------------------------+----------------------------+
数値の計算
GitHubにアップされている資料内にもありますが、手始めに数値計算から。ymlファイルを次のように書き換えて、再度実行します。
filters:
- type: eval
eval_columns:
- id: value * 2
- account: value / 3
- time: value
- purchase: value
- comment: value
- type: eval
eval_columns:
- id: value * 2
- account: value / 3
- time: value
- purchase: value
- comment: value
期待するデータの変換内容は
- idカラムの値が2倍になる
- accountカラムの値が3分の1になる
実行結果は次のようになりました。
+---------+--------------+-------------------------+-------------------------+----------------------------+
| id:long | account:long | time:timestamp | purchase:timestamp | comment:string |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| 2 | 10,954 | 2015-01-27 19:23:49 UTC | 2015-01-27 00:00:00 UTC | embulk |
| 4 | 4,941 | 2015-01-27 19:01:23 UTC | 2015-01-27 00:00:00 UTC | embulk jruby |
| 6 | 9,186 | 2015-01-28 02:20:02 UTC | 2015-01-28 00:00:00 UTC | Embulk "csv" parser plugin |
| 8 | 3,756 | 2015-01-29 11:54:36 UTC | 2015-01-29 00:00:00 UTC | NULL |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| id:long | account:long | time:timestamp | purchase:timestamp | comment:string |
+---------+--------------+-------------------------+-------------------------+----------------------------+
| 2 | 10,954 | 2015-01-27 19:23:49 UTC | 2015-01-27 00:00:00 UTC | embulk |
| 4 | 4,941 | 2015-01-27 19:01:23 UTC | 2015-01-27 00:00:00 UTC | embulk jruby |
| 6 | 9,186 | 2015-01-28 02:20:02 UTC | 2015-01-28 00:00:00 UTC | Embulk "csv" parser plugin |
| 8 | 3,756 | 2015-01-29 11:54:36 UTC | 2015-01-29 00:00:00 UTC | NULL |
+---------+--------------+-------------------------+-------------------------+----------------------------+
idカラムは期待通り2倍になっていますが、accountカラムは3分の1になったうえで小数点以下が切り捨てられてますね。整数同士の除算は整数になるRubyの仕様上、そうなっているのでしょうか。
Rubyの除算の仕様が原因だとすれば、除算している値のどちらかをfloatとして明示すれば、小数点以下も表示されるはずです。
そこで、ymlファイルを次のように書き換えてみます。
filters:
- type: eval
eval_columns:
- id: value * 2
- account: value / 3.to_f
- time: value
- purchase: value
- comment: value
- type: eval
eval_columns:
- id: value * 2
- account: value / 3.to_f
- time: value
- purchase: value
- comment: value
accountカラムの除算する数値を、floatとして明示しています。
ですが、結果は変わらず小数点が出ないまま…。
その後、色々試してみて分かりましたが、accountカラムの型がlong(整数)である以上、小数点以下は出ないようです。(accountカラムをdoubleにすると、最初のymlファイルでも小数点以下が表示されました)
embulk-filter-evalはデータ変換はするものの、根本的な型を変えたり、制約を越えられないようです。