見出し画像

【BigQuery+python】pythonプログラムからBQ上のデータを(ちょっとだけ)取りに行く

わたしへ。
どうせまた三ヶ月後にわからなくなるでしょうから、まとめておきます。
わたしより。

やりたいこと

アプリAが毎日データを収集してBQへ結果を突っ込んでいる、はず。
それが毎日動いて居るか確かめるため、アプリBがBQのデータをちょこっとだけ取ってきて、日付を見て、今日動いたかをチェックする。
そのために、処理日付のカラムだけ、最新から10行くらい取ってきたい。

=データフレームとか使うまでもないちょっとしたデータを、BQから取ってきたい。

公式ドキュメントはここにある

BigQuery API クライアント ライブラリ  |  Google Cloud

準備

$ pip install --upgrade google-cloud-bigquery

BigQuery用のクライアントライブラリをインストール。
必要に応じてサービスアカウントキーを設定しておく。

使い方

from google.cloud import bigquery

class BigQueryDataSource():
   def __init__(self, project_id):
       self.project_id = project_id
       self.client = bigquery.Client(project = project_id)
       
   def get(self, query):
       query_job = self.client.query(query)
       for row in query_job:
           print(f"{row['id']}/{row['time']}")
           print(f"{row[0]/row[1]}") # これでも上と同様に取得できる

if __name__ == '__main__':
   project_id = "project-no-id"
   
   target_table_name = "DataSetName.TableName"
   query = f'SELECT id, time FROM `{project_id}.{target_table_name}` ORDER BY time DESC LIMIT 10'
   
   datasource = BigQueryDataSource(project_id)
   datasource.get(query)

せつめい

from google.cloud import bigquery

まず、クライアントライブラリをインポート。

class BigQueryDataSource():
   def __init__(self, project_id):
       self.project_id = project_id
       self.client = bigquery.Client(project = project_id)
       
   def get(self, query):
       query_job = self.client.query(query)
       for row in query_job:
           print(f"{row['id']}/{row['time']}")
           print(f"{row[0]/row[1]}") # これでも上と同様に取得できる

接続を管理するためのクラスを作っておくと、後が楽。

プロジェクトIDは引数で貰わなくても、サービスアカウントキーで指定してあればデフォルトのプロジェクトに繋がるけど、チーム内で色んなプロジェクト跨いで開発してる場合、明示しておいた方がわかりやすい。

bigquery.Client()でクライアントのインスタンスを作る。プロジェクトIDを指定するならClient()に名前付き引数でproject = project_idを渡す。

クライアントインスタンスにクエリ文を渡してquery_jobを作る。

で、このquery_jobからのデータの取り出し方が肝。

今回の様なちょこっとだけ欲しいデータの場合、

1・リスト・辞書と同じようにquery_jobをforで回して一行ずつ取り出し
2・行オブジェクトに対してインデックスか添え字を指定すれば取れる

簡単!
インデックスは内部で自動的に振られてて、カラム名を指定すると内部でインデックス番号に変換してくれる。(for文の中でprint(row)してみると仕組みが解る)

呼び出すところ

if __name__ == '__main__':
   project_id = "project-no-id"
   
   target_table_name = "DataSetName.TableName"
   query = f'SELECT id, time FROM `{project_id}.{target_table_name}` ORDER BY time DESC LIMIT 10'
   
   datasource = BigQueryDataSource(project_id)
   datasource.get(query)

は、そんなに問題ないと思う。プロジェクトIDとテーブル名指定して、クエリ文書いて、インスタンス作って、getメソッドにクエリ渡してるだけ。

クエリ文書くときはBQのGUI上でクエリ掛けてみて、欲しいデータがちゃんと取れる事を確認→コピペ→テーブル名部分などを変数化、って手順でやるととても楽。
’(シングルクォーテーション)・”(ダブルクォーテーション)・`(←これ)の使い分けにだけ気をつける(例えば文字列全体をf""で囲んである場合、クエリ文の中に""が入るとぐちゃーってなってしまう)。
クエリ文の中ではシングル使えないから、全体をシングルで囲んでおけばぶつからないよ。


※ただし、今回の様なちょっと覗きに行くとき以外、BigQueryへ入れるような膨大なデータをforでぶん回して処理するとかちょっとpython的にカッコよくないので、本格的にデータ使って何かするならpandasでデータフレームに入れてごにょごにょするのが良い。が、今回は不要なので触れない。

この記事が気に入ったらサポートをしてみませんか?