背景
最近、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は学習コストが少し高いですが、その分カスタマイズ性が高くて良いですね。
プロジェクト全体のソースコードは以下になります。


