Metabaseのクエリ結果をPythonで取得する


はじめに

MetabaseのAPIをPythonで叩いてMetabaseで作成したクエリの結果を取得する方法のメモ。

環境

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G14042
$python --version
Python 3.7.3

事前準備

Metabase

インストール&起動

公式のドキュメント( https://www.metabase.com/start/oss/ )に記載されているように

docker run -d -p 3000:3000 --name metabase metabase/metabase

これだけでMetabaseがローカルの環境で動きます。便利!
ただ、立ち上がるまでに時間がかかるので、docker logs -f metabaseで起動が終わるまでみていた方が良さそうでした。
Chromeなどのブラウザでhttp://localhost:3000でアクセスできます。

ユーザ作成

ユーザ名:[email protected]
パスワード:P@ssw0rd

としてユーザを作っておきます。

DB

本来は既存のデータベース情報を登録して接続した上でクエリを投げますが、今回はサンプルとして用意されているものを使用するため、スキップします。

クエリ

「照会する」→「簡単な質問」からクエリを作成します。
下図にあるようにMetabaseに付属しているSample DatasetにあるORDERSテーブルからテキトーにSELECTしておきます。

このとき、クエリの番号がURLの/question/の次の番号になります(今は1)。
このクエリ番号を使ってPythonから結果を取得します。

MetabaseのPythonライブラリ

MetabaseはAPIが公開( https://www.metabase.com/docs/latest/api-documentation.html )されているので、ここにリクエストを投げればいいです。
ただPythonのライブラリがいくつかあるので、それを使います。
自分が調べた限り、現在3つライブラリがあります。

# ライブラリ名 URL 最終更新(2021年1月26日時点)
1 metabase-api https://pypi.org/project/metabase-api/
https://github.com/vvaezian/metabase_api_python
2021/01/18
2 metabasepy https://github.com/mertsalik/metabasepy 2020/10/30
3 metabase-py https://github.com/STUnitas/metabase-py 2020/5/28

今回は最終更新が直近であったmetabase-apiを使用します。
他のライブラリは試していないので、もしかしたらそちらの方が便利かもしれません。

pip install metabase-apiでインストールしておきます。

Pythonで取得する

run.py を下の内容で作成します。

run.py
from metabase_api import Metabase_API
import pandas as pd

mb = Metabase_API('http://localhost:3000', '[email protected]', 'P@ssw0rd')

out = mb.post('/api/card/1/query/json')

df = pd.DataFrame.from_records(out)

print(df.head())

最初にMetabase_APIにドメイン、ユーザのメールアドレス、パスワードを渡して認証します。
そのあとのmb.postでクエリの結果を取得しています。
これはAPI一覧( https://www.metabase.com/docs/latest/api-documentation.html#post-apicardcard-idqueryexport-format )によると、クエリ結果を得るのにPOSTで/api/card/:card-id/query/:export-formatを叩けばいいという仕様だったためです。
:card-idがクエリ番号です。
結果をpandasのDataFrameにしたかったので、json形式でフォーマットを指定しています。
outの中身はjsonのListになっているので、pd.DataFrame.from_recordsでpandasのDataFrameに変換しています。

$python run.py

実行するとMetabaseで表示されているクエリ結果を確かに得られました。

   ID  USER_ID
0   1        1
1   2        1
2   3        1
3   4        1
4   5        1