BigQueryで「Goの公式ライブラリで自前のテーブルにデータを流し込む」のはドキュメントを参考にすれば簡単にできましたが、それを読み込むところで詰まってしまいました。
bigquery: query job missing destination table
だのgoogleapi: Error 404: Not found: Job my-project:xxxxxxxxxxxxxxxxxxx, notFound
だのいろんなエラーに直面しながら、GCPUGで@sinmetalさんの助けもお借りしてようやく乗り越えられたので、備忘録として書き残しておきます。
つまづいた原因
一番の原因は、使っていた公式ライブラリcloud.google.com/go/bigqueryのバージョンが古かったこと。
超初歩的なミスですが、こういうことをしでかすとエラーメッセージでググっても解決策が見つからなくてとてもつらい。。
そして二番目の原因は、cloud.google.com/go/bigqueryのドキュメントの例が古かったこと。
実装例
2018年12月現在で最新の実装例はこちらです。
package main
import (
"fmt"
"log"
"context"
"google.golang.org/api/iterator"
"cloud.google.com/go/bigquery"
)
func main(){
ctx := context.Background()
client, err := bigquery.NewClient(ctx, "my-project")
if err != nil {
log.Fatal(err)
}
q := client.Query("SELECT year, SUM(number) as num FROM `bigquery-public-data.usa_names.usa_1910_2013` WHERE name = 'William' GROUP BY year ORDER BY year")
it, err := q.Read(ctx)
if err != nil {
log.Fatal(err)
}
for {
var values []bigquery.Value
err := it.Next(&values)
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Println(values)
}
}
公開データを使っているのでデータセットを用意する必要はありませんが、GCPで適当なプロジェクトを作成してBigQueryを有効にする必要があります。
my-project
の部分はご自分のプロジェクトIDにしてください。
(自前のテーブルを読み込むときは、クエリにProject IDを入れずに datasetId.tableId
の形式でも動きます)
注意点
公式のドキュメントの例では、下記のようにクエリがLegacy SQLになっています。
q := client.Query(`
SELECT year, SUM(number) as num
FROM [bigquery-public-data:usa_names.usa_1910_2013]
WHERE name = "William"
GROUP BY year
ORDER BY year
`)
it, err := q.Read(ctx)
if err != nil {
// TODO: Handle error.
}
現在はStandard SQLが標準になっているようなので、FROM句のところを[projectId:datasetId.tableId]
の形式にするとエラーが発生します。
最新のライブラリであればエラーメッセージでStandard SQLの形式で書くよう促されるのですが、古いライブラリだとbigquery: query job missing destination table
などの見当外れなエラーメッセージで「え??」ってなってしまいます。
もし同じような問題にぶち当たっている方がいたら、とりあえず $ go get -u cloud.google.com/go/bigquery
をトライしてください。