背景
最近、BigQueryにおけるデータ変換を行うツールとしてdbtを使い始めました。
しかしこのdbt、プロジェクトごとに一つのBigQueryデータセットを作る仕様になっています。
一方、使い方によってはディレクトリごとにBigQueryデータセットを作成したいケースもあるかと思います。本記事ではカスタムマクロによってそれを実現したいと思います。
用語説明
dbtとBigQueryでは用語の使い方が紛らわしく、少々混乱しそうになりますが、以下のようになっています。本記事ではわかりやすくするため、接頭語としてdbt/BigQueryをつけて記述します。
dbt | BigQuery |
---|---|
プロジェクト | ー |
データベース | プロジェクト |
スキーマ | データセット |
やりたいこと
dbtではデフォルトでは、profiles.yml
の dataset
に設定した値をBigQueryデータセット名として設定されます。例えば dataset
に dbt_test
を設定していると以下のようになります。
また、dbt_profiles.yml
で +schema: foo
を設定すると以下のように、<default schema>_<custom schema>
になります。
本記事ではこれに対し以下のようなファイル構成であった場合、ディレクトリ名である example
をそのままBigQueryデータセット名に設定することを目指します。
├── models
│ └── example
│ ├── my_first_dbt_model.sql
│ ├── my_second_dbt_model.sql
│ └── schema.yml
やり方
dbt では generate_schema_name
マクロを定義することで、好きなスキーマを設定することができます。
generate_schema_name
には custom_schema_name
と node
の二つの引数が渡されます。
この node
の型は ParsedModelNode
で、以下の値が設定されています。
パラメータ | 概要 | 例 |
---|---|---|
raw_sql | SQLファイルの内容 | |
database | BigQueryプロジェクト名 | |
schema | デフォルトのBigQueryデータセット名 | 'dbt_test' |
fqn | Fully Qualified Name | ['(dbtプロジェクト名)', 'example', 'my_first_dbt_model'] |
unique_id | プロジェクトで一意なモデルID | 'model.(dbtプロジェクト名).my_first_dbt_model' |
package_name | dbtプロジェクト名 | |
root_path | dbtプロジェクトディレクトリまでのパス | |
path | モデルディレクトリ内のモデルファイルのパス | 'example/my_first_dbt_model.sql' |
original_file_path | dbtプロジェクトディレクトリ内でのパス | 'models/example/my_first_dbt_model.sql' |
name | モデル名 | 'my_first_dbt_model' |
alias | エイリアス | 'my_first_dbt_model' |
ディレクトリ名をBigQueryデータセット名に設定するには fqn
または path
が使えそうです。
今回は fqn
を使用して以下のマクロを組みました。
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set fqn = node['fqn'] -%}
{%- set schema = '_'.join(fqn[1:-1]) -%}
{{ schema }}
{%- endmacro %}
これで dbt run
するとディレクトリ名の example
がBigQueryデータセットに設定され、やりたかったことができました。
おわりに
dbtは学習コストが少し高いですが、その分カスタマイズ性が高くて良いですね。
プロジェクト全体のソースコードは以下になります。