LoginSignup
3
4

More than 5 years have passed since last update.

HerokuからgolangでBigQueryにつなぐ方法

Last updated at Posted at 2017-07-22

結構ハマって調べたので、まとめました。2017-07-22 時点の情報です。
作業しながら見つけたので、少し間違っている可能性はあります。

対象読者

  • BigQueryを用意したがAPIとして呼びたい
  • Go(golang)を使いたい
  • Herokuなど、Webアプリケーションから動かしたい

手順

ざっと以下の手順。

  1. GCP上でサービスアカウントを登録
  2. Herokuで環境変数の設定
  3. Goから呼べるようにする

※Herokuの使い方やBigQueryの作成、細かい用語の説明などは別の方のドキュメントを参考にしてください。

GCP上でサービスアカウントの登録

対象のプロジェクトでGCPの「IAMと管理」を開く

1.png

サービスアカウントを追加

役割は以下。役割を間違えると、403 Access Deniedとなります。

  • BigQuery データ閲覧者
  • BigQuery ユーザー

2.png

Json形式で鍵をダウンロード

手順に従えばダウンロードは問題なくできます。

Herokuで環境変数の設定をする

Herokuの以下画面で環境変数を設定する。
KEYを「GOOGLE_APPLICATION_CREDENTIALS」、VALUEを上記ダウンロードしたJSONファイルをコピー&ペースト

3.png

※コマンドから設定も可能です。

Goから呼べるようにする

サンプルコードは以下です。一応ローカル(1.8.1)では動きました。
実際にはAPIとしてHerokuにデプロイしているので、このコードをデプロイしたわけではありません。

注意
プロジェクトIDも環境変数に入れいています。ローカル環境では以下のようにして設定しました。

# xxxにはプロジェクトIDとダウンロードしたjsonファイルです。
export PROJECT_ID=xxxxx
export GOOGLE_APPLICATION_CREDENTIALS="$(cat xxxxxx.json)"

goのソースコードは以下です。gistにも似たのは置いています。

package main

import (
    "cloud.google.com/go/bigquery"
    "fmt"
    "golang.org/x/net/context"
    "golang.org/x/oauth2/google"
    bq "google.golang.org/api/bigquery/v2"
    "google.golang.org/api/iterator"
    "google.golang.org/api/option"
    "os"
)

func main() {
    json := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
    ctx := context.Background()
        // project ID も環境変数に入れています。
    projectID := os.Getenv("PROJECT_ID")
    jwtConfig, err := google.JWTConfigFromJSON([]byte(json), bq.BigqueryScope)
    if err != nil {
        fmt.Printf("Json load error: %v\n", err)
    }
    ts := jwtConfig.TokenSource(ctx)
    client, err := bigquery.NewClient(ctx, projectID, option.WithTokenSource(ts))
    if err != nil {
        fmt.Printf("Client create error: %v\n", err)
    }

                // SQL
    bqSql := " select * from [zip.zip] order by zip limit 10"
    fmt.Println(bqSql)

    q := client.Query(bqSql)
    it, err := q.Read(ctx)
    if err != nil {
        fmt.Printf("Error2: %v\n", err)
    }
    for {
        var values []bigquery.Value
        err := it.Next(&values)
        if err == iterator.Done {
            break
        }
        if err != nil {
            fmt.Printf("Error3: %v\n", err)
        }
        fmt.Printf(values[0].(string))
        fmt.Printf(values[1].(string))
    }
}

関連リンク

3
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4