GoでBigQueryクライアントを実装してBigQueryからデータを取ってくる
会社のある偉大な先輩は、以前こう言った。
「BigQueryは全人類が使えるようになるべきだ」と。
僕は、最近BigQueryの学習を始めた。
BigQueryの学習の一環として、BigQueryクライアントを実装してみた。
やること
GoのコードからBigQueryクライアントを実装してSQLを走らせ、データをローカルに取得して、コマンドラインに表示させる。
クライアントライブラリって何?
好みの言語から、Google Cloud APIsをHTTPに直接リクエストしたり、RPC callsしたりして使うためのライブラリ。
公式ドキュメント
準備
クライアントライブラリのインストール
BigQueryのクライアントライブラリを以下のコマンドでインストールする。
go get cloud.google.com/go/bigquery
認証
BigQueryのAPIを使用するためには、アカウント認証を行う必要があるので、それを行う。
以下のサイトが参考になる。
FluentdでGoogle BigQueryにログを挿入してクエリを実行する
Google Cloud Platformをローカルから利用するための準備
BigQueryクライアントを使う
手順
BigQueryクライアントをGoで実装するためには、大まかに以下のような手順を踏む。
- 空のcontextを生成
- contextとprojectIDを元にBigQuery用のclientを生成
- Queryを生成
- Queryを読み込んで、resultを取得するためのIteratorを生成
- Iteratorを回して順次結果を取得
詳細は、コード中にコメントとして記述している
なお、以下の公式ドキュメントを参考にしている
BigQuery クライアント ライブラリの公式ドキュメント
コード
package main import ( "cloud.google.com/go/bigquery" "context" "fmt" "google.golang.org/api/iterator" "log" ) func main() { fetchBigQueryData() } // BigQueryで実行するためのSQL const QUERY = ` SQL ` func fetchBigQueryData() { // 空のcontextを生成 ctx := context.Background() // プロジェクトのID projectID := "プロジェクトのID" // contextとprojectIDを元にBigQuery用のclientを生成 client, err := bigquery.NewClient(ctx, projectID) if err != nil { log.Printf("Failed to create client:%v", err) } // 引数で渡した文字列を元にQueryを生成 q := client.Query(QUERY) // 実行のためのqueryをサービスに送信してIteratorを通じて結果を返す // itはIterator it, err := q.Read(ctx) if err != nil { log.Println("Failed to Read Query:%v", err) } for { // BigQueryの結果から、中身を格納するためのBigQuery.Valueのsliceを宣言 // BigQuery.Valueはinterface{}型 var values []bigquery.Value // 引数に与えたvaluesにnextを格納する // Iteratorを返す // これ以上結果が存在しない場合には、iterator.Doneを返す // iterator.Doneが返ってきたら、forを抜ける err := it.Next(&values) if err == iterator.Done { break } if err != nil { log.Println("Failed to Iterate Query:%v", err) } fmt.Println(values) } }
実際に簡単なQueryを投げるように実装してみた
今回は、BigQueryのコンソールにデフォルトで表示されるPublic Datasetsの中から
bigquery-public-data:usa_namesのusa_1910_2013のデータを使用した。
このテーブルに対して、'Mary’という名前を持つデータを取得して、コマンドラインに表示する。
実装の流れは先ほどと全く変わらない。
今回は、BigQueryクライアントの実装を目的としているため、SQLは以下のようにかなり簡素なものになっている。
SELECT * FROM [bigquery-public-data:usa_names.usa_1910_2013] WHERE name = 'Mary' LIMIT 100
実装
package main import ( "cloud.google.com/go/bigquery" "context" "fmt" "google.golang.org/api/iterator" "log" ) func main() { fetchBigQueryData() } // BigQueryで実行するためのSQL const QUERY = ` SELECT * FROM [bigquery-public-data:usa_names.usa_1910_2013] WHERE name = 'Mary' LIMIT 10 ` func fetchBigQueryData() { // 空のcontextを生成 ctx := context.Background() // プロジェクトのID projectID := "プロジェクトのID" // contextとprojectIDを元にBigQuery用のclientを生成 client, err := bigquery.NewClient(ctx, projectID) if err != nil { log.Printf("Failed to create client:%v", err) } // 引数で渡した文字列を元にQueryを生成 q := client.Query(QUERY) // 実行のためのqueryをサービスに送信してIteratorを通じて結果を返す // itはIterator it, err := q.Read(ctx) if err != nil { log.Println("Failed to Read Query:%v", err) } for { // BigQueryの結果から、中身を格納するためのBigQuery.Valueのsliceを宣言 // BigQuery.Valueはinterface{}型 var values []bigquery.Value // 引数に与えたvaluesにnextを格納する // Iteratorを返す // これ以上結果が存在しない場合には、iterator.Doneを返す // iterator.Doneが返ってきたら、forを抜ける err := it.Next(&values) if err == iterator.Done { break } if err != nil { log.Println("Failed to Iterate Query:%v", err) } fmt.Println(values) } }
実行結果
[AK F 1912 Mary 9] [AK F 1916 Mary 18] [AK F 1918 Mary 27] [AK F 1919 Mary 22] [AK F 1923 Mary 26] [AK F 1925 Mary 24] [AK F 1926 Mary 39] [AK F 1927 Mary 30] [AK F 1930 Mary 35] [AK F 1931 Mary 41]
参考にさせていただいたサイト
BigQuery クライアント ライブラリの公式ドキュメント
Google BigQuery API へのリクエストを認証する
FluentdでGoogle BigQueryにログを挿入してクエリを実行する
Google Cloud Platformをローカルから利用するための準備
※ Qiitaでも同一記事を投稿している qiita.com