はじめに
みなさん、BigQueryが絡む処理のローカル開発やテストどうしてますか?BigQueryは公式のエミュレーターが提供されていないのでけっこう困ること多いんじゃないでしょうか?
私はとりあえず、ローカルではなく専用の環境を用意してそこに接続する形にしていましたが、業務委託の方などに入っていただくことが増えると権限周りで少々悩ましいことも多いです。
ただ数ヶ月前に、goccyさんという方が開発されたGo製のOSSbigquery-emulator
が公開され、こうした問題に解消の兆しが見えてきました。(開発者の方にはリスペクトしかありません!)
少し前までは提供されていない機能も多かったのですが、開発が進み環境が整ってきているようなので、今回はこのbigquery-emulator
を触ってみようと思います。
実行準備
今回は提供されているdockerイメージを利用して作業をしていくので、リポジトリのクローンは不要です。
※ docker, docker-composeを利用できるようにしておいてください
環境
- OS: macOS Big Sur(11.1)
やってみる
CLIからのクエリ実行
まずは起動 -> CLIからのクエリ実行を確認します。
ディレクトリ構成は以下の通りです。
.
├── docker-compose.yaml
└── testdata
└── data.yaml
ここだけであればcomposeは必須でないですが、後でpythonコンテナから接続したいのでcomposeを利用しています。
中身は以下の通り
version: '3.7'
services:
bq:
image: ghcr.io/goccy/bigquery-emulator:latest
ports:
- "9050:9050"
volumes:
- ./testdata:/testdata
command: "bigquery-emulator --project=test --data-from-yaml=../testdata/data.yaml"
./testdata/data.yaml
には起動時に挿入するデータを指定しておきます。(これはリポジトリのものをそのまま拝借)
projects:
- id: test
datasets:
- id: dataset1
tables:
- id: table_a
columns:
- name: id
type: INTEGER
- name: name
type: STRING
data:
- id: 1
name: alice
- id: 2
name: bob
コンテナを立ち上げれば9050番ポートでbigquery-emulatorが起動し、test
という名前のプロジェクト名でdata.yaml
に記述したデータについてクエリをかけられるようになるので確認してみましょう!
以下、ターミナルから実行します。
# 起動
$ docker-compose up -d
# クエリ
$ bq --api http://0.0.0.0:9050 query --project_id=test "SELECT id, name FROM dataset1.table_a WHERE id = 1"
+----+-------+
| id | name |
+----+-------+
| 1 | alice |
+----+-------+
無事にクエリ結果が得られました。
pythonクライアントからのクエリ実行
ここまででもローカルで実行できることに感動ものなのですが、せっかくなのでpythonからも接続してみます。
pythonコンテナ用にDockerfileを追加し、docker-compose.yamlを修正します。
Dockerfileでは、BigQueryのクライアントをインストールしておきます。
$ touch Dockerfile
FROM python:3.8
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install google-cloud-bigquery
COPY app app
WORKDIR /app
version: '3.7'
services:
# 追記
app:
restart: always
build: .
tty: true
volumes:
- ./app:/app
.
.
.
pythonで実行するコードはapp/main.py
に以下の通り追加します。
$ mkdir app
$ touch app/main.py
from google.cloud import bigquery
from google.auth.credentials import AnonymousCredentials
project_id = "test"
client = bigquery.Client(
project=project_id,
credentials=AnonymousCredentials(),
client_options={
"api_endpoint": "http://host.docker.internal:9050",
}
)
table_name = f"{project_id}.dataset1.table_a"
query = f'''
SELECT id, name FROM `{table_name}`
'''
result = client.query(query)
for row in result:
print(row)
AnonymousCredentials
はエミュレーターなどのためにダミーで渡すことのできるcredentialsクラスで、こうしておくことで認証情報を渡さずに認証部分を突破できます。
また今回はコンテナ間で接続するので、エンドポイントがhttp://host.docker.internal:9050
になる点にも注意してください。
それではコンテナをbuildしてから実行してみます。
$ docker-compose build --no-cache
$ docker-compose up -d
# 実行
$ docker-compose exec app python main.py
以下の通りクエリ結果が得られました。
Row((1, 'alice'), {'id': 0, 'name': 1})
Row((2, 'bob'), {'id': 0, 'name': 1})
最後に
今回はbigquery-emulatorを少し触ってみました。
すでにおおよそ整備されているので非常に簡単に扱えそうですね!感謝!
これを機にローカル開発環境やテスト環境を本格的に整備して行こうかなーなど考えてます。
というわけで今回はこれにて!