What is it, naokirin?

Embulkでバッチ処理をしてみよう 其の3

前回はコマンドや設定周りについてみていきました。

前回: Embulkでバッチ処理をしてみよう 其の2 - what is it, naokirin?

今回は liquid テンプレートによる設定の書き方を見ていきます。実際にEmbulkを利用していくことになった際に環境ごとに変えたり、複数の処理を共通化したくなる場面が出てくることがあり、そのような場合に非常に有用です。

今回も以下のリポジトリを利用していきます。

github.com

example_liquid をチェックアウトして確認して見るようにしてください。

liquid テンプレート

早速ですがliquidテンプレートを利用した設定を見ていきましょう。

in:
  type: randomj
  rows: 10
  threads: 1
  primary_key: id
  schema:
    - {name: id, type: long}
    - {name: value, type: string, length: {{ env.VALUE_LENGTH }} }

# 省略

前回と変わったところとして、 in の部分で設定していた valuelength の項目が {{ env.VALUE_LENGTH }} になっています。これにより環境変数を利用することができます。

それでは実際に VALUE_LENGTH環境変数を設定して実行してみましょう。

$ docker build -t embulk_examples .
$ docker run -it --rm -e VALUE_LENGTH=5 embulk_examples sh -c '/embulk/embulk preview config/example_3.yaml.liquid'
Embulk v0.9.12
[WARN] (main): DEPRECATION: JRuby org.jruby.embed.ScriptingContainer is directly injected.
[INFO] (main): Gem's home and path are set by default: "/root/.embulk/lib/gems"
[INFO] (main): Started Embulk v0.9.12
[INFO] (0001:preview): Loaded plugin embulk-input-randomj (0.5.1)
[INFO] (0001:preview): Loaded plugin embulk-filter-column (0.7.1)
+---------+------------------+
| id:long | user_name:string |
+---------+------------------+
|       1 |            Gi1DA |
|       2 |            SIRB1 |
|       3 |            s5FWK |
|       4 |            kcjZK |
|       5 |            vzv6m |
|       6 |            Dc6AT |
|       7 |            EHzkP |
|       8 |            PdfGj |
|       9 |            QF2yo |
|      10 |            GaIh5 |
+---------+------------------+

出力結果の文字列が5文字になりました。このようにliquidを用いることで環境変数を利用することができます。

liquid テンプレートを利用する場合、 .liquid 拡張子をつけることで有効化されます。それでは実際にいくつかのテンプレートの書き方を列挙していきます。

{{ xxx }} : その場に展開する

{{ xxx }} とすることでその場に xxx が展開されます。定数や式の場合はその結果が展開されるようになります。

env.xxx : 環境変数を参照する

env.xxx と書くことで xxx という環境変数を利用することができます。先ほど例を出したので、詳細は割愛します。

{% assign cons = value %} : 定数を定義する

{% assign cons = value %} と書くことで cons という定数を value という値で定義できます。これ単体ではただ定数を定義するだけですが、その他の機能と併用することで共通化に非常に便利です。

{% include 'included' %}

{% include 'included' %} を用いることで他のliquidテンプレートファイルを読み込むことができます。これにより設定を組み合わせて利用するなどができます。

注意点として include で指定するには、 _included.yml.liquid のように、ファイル名に _ が先頭についている必要があります。また、 .yaml.liquid ではなく .yml.liquid でなければならない点にも注意が必要です。


最後に上記を利用した設定を実行してみましょう。 example_liquid をチェックアウトして実行してみましょう。

example_4.yaml.liquid

{% include 'consts' %}
{% include 'in' %}

filters:
  - type: column
    columns:
      - {name: id, type: long}
      - {name: user_name, src: value}
out:
  type: command
  command: "cat - > '{{ output_path }}'"
  formatter:
    type: fast_jsonl

_in.yml.liquid

in:
  type: randomj
  rows: {{ env.ROWS }}
  threads: 1
  primary_key: id
  schema:
    - {name: id, type: long}
    - {name: value, type: string, length: 10 }

_consts.yml.liquid

{% assign output_path = '/workdir/output.txt' %}

実際に上記の設定を用いたEmbulkの実行をしてみましょう。

$ docker build -t embulk_examples .
$ docker run -it --rm -v $(pwd)/output.txt:/workdir/output.txt -e ROWS=5 embulk_examples sh -c '/embulk/embulk run config/example_4.yaml.liquid'
$ cat output.txt
{"id":1,"user_name":"ICEmzdxcYK"}
{"id":2,"user_name":"UpFr25zsYY"}
{"id":3,"user_name":"sB8TZb77Ow"}
{"id":4,"user_name":"MQf9Oso6wH"}
{"id":5,"user_name":"yBJzic3kDZ"}

このようにliquidテンプレートを用いることで設定の共通化や環境ごとの切り替えを達成することができます。

liquidテンプレートでは forif などの条件分岐や繰り返しもできますが、やりすぎると複雑になって設定の見通しが悪くなるため、極力使用せずにできるのであれば、使用せず書いていくほうが良いかと思います。