BigQueryの集計結果をテーブルに保存した後GCSにエクスポートしてみた

こういう細かいネタもブログに残していこうと思います。
ってブログ書く度に決意しているんだけど続かないですね...

BigQueryの集計結果をテーブルに保存

使うpackageは cloud.google.com/go/bigquery です。このpackageはまだbetaらしいです。
google.golang.org/api/bigquery/v2 でもできるはずですが、cloud.google.com/go/bigqueryのほうが簡潔に書けそうな感じがしました。

コードはこんな感じ
AppEngine上で動かすコードになっていますが、一部変更すれば、AppEngine以外でも動くはずです。

package hoge

import (
    "context"

    "cloud.google.com/go/bigquery"
    "google.golang.org/appengine"
)

// BigQueryのSchema例
type schema struct {
    UserID   string
    UserName string
}

const datasetID = "test"
const tableID = "test"
const query = ""

// 関数名適当で申し訳ない
func bq(ctx context.Context) error {
    client, err := bigquery.NewClient(ctx, appengine.AppID(ctx))
    if err != nil {
        return err
    }

    // 集計結果を保存するDatasetを作成
    d := client.Dataset(datasetID)
    d.Create(ctx, &bigquery.DatasetMetadata{
        Location: "US", // お好みで
    })

    // 集計結果を保存するTable作成
    s, err := bigquery.InferSchema(schema{})
    if err != nil {
        return err
    }
    table := client.Dataset(datasetID).Table(tableID)
    if err := table.Create(ctx, &bigquery.TableMetadata{Schema: s}); err != nil {
        return err
    }

    // Queryの準備
    q := client.Query(query)
    q.WriteDisposition = bigquery.WriteTruncate // お好みで
    q.Dst = &bigquery.Table{
        ProjectID: appengine.AppID(ctx),
        DatasetID: datasetID,
        TableID:   tableID,
    }
    // 最大レスポンスサイズを超えそうだったらtrueにする
    // see: https://cloud.google.com/bigquery/querying-data#large-results
    q.AllowLargeResults = true

    job, err := q.Run(ctx)
    if err != nil {
        return err
    }
    jobStatus, err := job.Wait(ctx)
    if err != nil {
        return err
    }
    if err := jobStatus.Err(); err != nil {
        return err
    }
    return nil
}

BigQueryのテーブル指定してをGCSにexport

CSVファイルにしてexportしてみます

package hoge

import (
    "cloud.google.com/go/bigquery"
    "google.golang.org/appengine"
)

const datasetID = "test"
const tableID = "test"
// export先を指定
const gcsURI = "" // TODO

func export(ctx context.Context) error {
    client, err := bigquery.NewClient(ctx, appengine.AppID(ctx))
    if err != nil {
        return err
    }

    gcsRef := bigquery.NewGCSReference(gcsURI)
    gcsRef.SourceFormat = bigquery.CSV // defaultはCSV
    gcsRef.FieldDelimiter = ","        //defaultは ","
    gcsRef.AllowQuotedNewlines = true

    extractor := client.Dataset(datasetID).Table(tableID).ExtractorTo(gcsRef)
    extractor.DisableHeader = false // お好みで
    job, err := extractor.Run(ctx)
    if err != nil {
        return err
    }
    status, err := job.Wait(ctx)
    if err != nil {
        return err
    }
    if status.Err(); err != nil {
        return err
    }
    return nil
}

まとめ

  • cloud.google.com/go/bigquery を使って集計結果の保存とGCSへのexportをやってみました
  • bigquery packageを初めて使ったので調査のコストは少しありました
  • UTF-8でexportされるのでExcelで開くと文字化けするかも...