jaffle-shop プロジェクトを COMETA でメタデータ管理してみる

# 概要

dbt はデータモデリングツールとして、データの変換を行うことができますが、同時にメタデータの管理も可能です。例えば、プロパティや設定を利用したビジネスメタデータ、モデルの生成に利用されるSQLなどのテクニカルメタデータ、あるいは dbtコマンドの実行に関するオペレーショナルメタデータなどがあります。
今回[COMETA](https://documents.trocco.io/cometa/docs/about-data-catalog-v2)にdbtメタデータ連携機能が追加され、model、source、snapshot、seed リソースの一部メタデータをCOMETA上のアセット[^1]に関連付けできるようになりましたので、その設定と機能について紹介します。


## dbt プロジェクトの準備

今回は、dbt のサンプルプロジェクトである [jaffle-shop](https://github.com/dbt-labs/jaffle-shop) を用いて COMETA でのメタデータ連携を試してみます。

### 環境セットアップ

jaffle-shop プロジェクトをクローンします。

```bashsh
git clone git@github.com:dbt-labs/jaffle-shop.git
```

dbt Cloud では `profiles.yml` ファイルが含まれていないため、使用するアダプターに応じて適宜設定します。今回は BigQuery 環境用の設定を追加し、適切な接続情報を記述します。

```yaml:profiles.yml
default:
  target: dev
  outputs:
    dev:
      type: bigquery
      method: service-account
      project: {your_project}
      dataset: test_jaffle_shop
      keyfile: {path/to/key/file.json}
      location: {your_location}
```

### seed データの設定とプロジェクト調整

jaffle-data ディレクトリのデータを参照できるように、`dbt_project.yml` に seed-paths の設定を追加します。

```yaml:dbt_project.yml
seed-paths: ["seeds", "jaffle-data"]
```

また、[データセット名をカスタマイズする](https://github.com/hgkcho/jaffle-shop/commit/27b3a57ec01848d93431a8312ad858850e574696)ため、`schema: raw` の部分を `test_jaffle_shop_raw` に置き換えます。



```diff:dbt_project.yml
 sources:
   - name: ecom
-    schema: raw
+    schema: test_jaffle_shop_raw
     description: E-commerce data for the Jaffle Shop

```


```diff:macros/generate_schema_name.sql
-    {# seeds go in a global `raw` schema #}
+    {# seeds go in a global `test_jaffle_shop_raw` schema #}
```


次に、Python の仮想環境を作成し、dbt での依存関係をインストールします。

```sh
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
python3 -m pip install dbt-core dbt-bigquery
```

### dbt コマンドの実行

以下のコマンドを使用して、依存パッケージをインストールし、BigQuery にテーブルを作成します。

```sh
dbt deps
dbt seed
dbt run
```

`dbt build` は `run`、`test`、`snapshot`、`seed` の各コマンドをまとめて実行します。 次に、dbt のドキュメント生成コマンドを使用してメタデータを作成します。

```sh
dbt docs generate
```

これで、`catalog.json` と `manifest.json` が生成され、COMETA でメタデータとして利用する準備が整いました。

## COMETA への dbt メタデータの連携設定

現状成果物の置き場所として S3 をサポートしています。生成された `catalog.json` と `manifest.json` を任意の S3 バケットに配置し、そのバケットに対するアクセス権限を持つ IAM ロールを用意します。COMETA での設定項目は以下の通りです。

- IAM ロール ARN
- 外部 ID
- バケット名
- パスプレフィックス

上記の情報を入力し、連携を保存することでメタデータの連携が完了します。


![スクリーンショット 2024-10-30 18.28.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/a12e19c7-2e04-bf99-f8ac-170f308f0a96.png)

## 連携ジョブの実行

連携設定画面右上のジョブ実行ボタンを押すことで dbt のメタデータファイルの読み込みが行われます。
現状のジョブキック手段としては以下をサポートしています。

- 日時バッチのデータストア連携ジョブの後に実行
- UIからの手動実行

![スクリーンショット 2024-10-30 18.32.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/a71e10de-8496-3996-3f2f-12cf02d3a36f.png)


## COMETA でのメタデータ管理

dbt で YAML ファイルを使用してテーブルやカラムに関するメタデータを設定している場合、その情報が COMETA のアセット詳細画面上で確認可能になります。COMETA は model、source、snapshot、seed といった dbtリソースに紐づくメタデータの可視化に対応しています。

## モデル stg_products の確認

今回は stg_products を例にしてみます。stg_products はステージング層のデータとして定義され、生データから加工して扱いやすいようにしているモデルです。`models/staging/stg_products.sql` に以下のようなモデルが定義されています。


```sql:models/staging/stg_products.sql
with
source as (
    select * from {{ source('ecom', 'raw_products') }}
),
renamed as (
    select
        sku as product_id,
        name as product_name,
        type as product_type,
        description as product_description,
        {{ cents_to_dollars('price') }} as product_price,
        coalesce(type = 'jaffle', false) as is_food_item,
        coalesce(type = 'beverage', false) as is_drink_item
    from source
)

select * from renamed
```

また、モデルに対応する `stg_products.yml` には以下のようなメタデータが記述されています。YAMLファイルを記述することでリソースにプロパティを定義することができます。[詳しくはこちら](https://docs.getdbt.com/reference/configs-and-properties)

```yaml:models/staging/stg_products.yml
models:
  - name: stg_products
    description: Product (food and drink items that can be ordered) data with basic cleaning and transformation applied, one row per product.
    columns:
      - name: product_id
        description: The unique key for each product.
        data_tests:
          - not_null
          - unique
```

COMETA に連携することで以下のように stg_productsアセットにdbtのメタデータ情報が付与されます。

![スクリーンショット 2024-10-30 16.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/5d946ee0-a50b-0c73-89fb-654220f73338.png)


product_id カラムに関しても連携されていることを確認できます。

![スクリーンショット 2024-10-31 12.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/1e0ff7d7-46ff-a130-8409-6e99116793aa.png)


## カラムリネージ機能

また、COMETA のカラムリネージ機能により、stg_productsアセットがどのように他のアセットで使用されているかを可視化できます。特に、アップストリームおよびダウンストリームのアセットを確認することで、各カラムの影響範囲を把握できます。実線で繋がれている場合はデータの参照のみをしており、点線で繋がれていれば参照と何かしらの加工が行われていることを示します。例えば、`sku` や `name` はリネームのみが行われている一方、`product_price` や `is_food_item` では何らかの変換処理が行われていることがわかります。

![スクリーンショット 2024-10-30 16.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/23c336fc-548e-3019-a5a7-b5dbb362e5bf.png)


## タグやメタ情報の連携

タグやメタ情報もCOMETA にインポートすることも可能です。デフォルトで用意されていたYAMLファイルを修正してタグやメタ情報を設定します。以下のように `stg_supplies` モデルに deprecated タグと owner メタ情報を設定し再度メタデータ連携ジョブを実行します。

```yaml
models:
  - name: stg_supplies
    config:
      tags:
        - deprecated
    meta:
      owner: dev-team
    description: >
      List of our supply expenses data with basic cleaning and transformation applied.
```

タグやメタの情報が取り込まれました。

![スクリーンショット 2024-10-30 17.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677442/1fd87009-460f-29b3-3237-8b46e789e7fa.png)

# まとめ

dbtで管理しているリソースの description, meta, tag, カラムリネージといったメタデータを COMETAのアセットに関連付けできるようになりました。

# 今後

今後もdbtを通して以下のような機能の拡充をしていきたいと思います。

- 連携対象となるプロパティや設定の拡充
- リレーションの自動生成
- リネージの拡大BIアセットなどのダウンストリームアセットやS3などのsourceとなるアップストリームアセットを表示する
- metaやタグをCOMETAの機能にバインドしてインポートする機能

[^1]:COMETA上でカタログ管理する対象であるデータベース、スキーマ、テーブル、カラムなど https://documents.trocco.io/cometa/docs/table-information-v2