はじめに
GolangでBigQueryをざつに扱っています。
GolangでBigQueryのtableを作成時のSchema指定方法についての自分メモです。
この記事のサンプルコードは以下においてあります。
アジェンダ
1. schemaの指定方法は何があるか
まずは基本的なtable create時のschema指定方法ですが、以下のように行います。
schema := /* 何らかの方法でSchemaを生成 */ metaData := &bigquery.TableMetadata{Schema: schema} t := client.Dataset(dataset).Table(table) if err := t.Create(ctx, metaData); err != nil { return err }
/* 何らかの方法でSchemaを生成 */
ですが、
主には以下の3点があると思います。
- bigquery.Schema: field個別にSchema指定
- bigquery.InferSchema: struct + タグでSchema指定してみる
- bigquery.SchemaFromJSON: jsonファイルでSchema指定
ということで、以下では3つの方法を試してみます。
おもむろにサンプルコードを載せて解説は省きます。
2. bigquery.Schema: field個別にSchema指定
fieldを個別にschemaを指定する方法です。
// client ctx := context.Background() client, err := bigquery.NewClient(ctx, projectID) if err != nil { return err } // schema schema := bigquery.Schema{ {Name: "id", Required: true, Type: bigquery.StringFieldType}, {Name: "data", Required: false, Type: bigquery.StringFieldType}, {Name: "timestamp", Required: false, Type: bigquery.TimestampFieldType}, } metaData := &bigquery.TableMetadata{Schema: schema} // create table t := client.Dataset(dataset).Table(table1) if err := t.Create(ctx, metaData); err != nil { return err }
3. bigquery.InferSchema: struct + タグでSchema指定してみる
structにbigqueryタグを指定し、bigquery.InferSchemaでschemaを作成する方法です。
type Item struct { ID string `bigquery:"id"` Data string `bigquery:"data"` Timestamp time.Time `bigquery:"timestamp"` } func createTableBySchema2() error { // client ctx := context.Background() client, err := bigquery.NewClient(ctx, projectID) if err != nil { return err } // schema schema, err := bigquery.InferSchema(Item{}) metaData := &bigquery.TableMetadata{Schema: schema} // create table t := client.Dataset(dataset).Table(table2) if err := t.Create(ctx, metaData); err != nil { return err } return nil }
4. bigquery.SchemaFromJSON: jsonファイルでSchema指定
jsonからSchemaを作成する方法です。
ファイルでなくても大丈夫ですが、この例ではファイルから読み込んでいます。
// client ctx := context.Background() client, err := bigquery.NewClient(ctx, projectID) if err != nil { return err } // schema path := "./schema/schemaSampleTable3.json" buf, err := ioutil.ReadFile(path) if err != nil { panic(err) } schema, err := bigquery.SchemaFromJSON(buf) metaData := &bigquery.TableMetadata{Schema: schema} // create table t := client.Dataset(dataset).Table(table3) if err := t.Create(ctx, metaData); err != nil { return err }
5. どれが良いのか?
1つのポイントとして、nullable指定したいか?がキーになりそうです。
InferSchema(struct + タグ)指定ですが、
以下のようにnullable指定ができません。(というかやり方を調べたけどわからなかった)
2. bigquery.Schema: field個別にSchema指定
のテーブル
3. bigquery.InferSchema: struct + タグでSchema指定してみる
のテーブル
4. bigquery.SchemaFromJSON: jsonファイルでSchema指定
のテーブル
そのため、nullを許容する場合はInferSchema以外
が良さそうです。
なぜ今回の調査をしたか
なぜ今回調査をしたかですが、
「GolangでAPI(json形式)を受けて、その結果をBigQueryに保存したい」
という要件がありました。
この場合、APIの結果jsonとBigQueryのschemaのstructを一緒にできないか?と考えていました。
以下のような感じですね。
// APIの結果jsonとbigqueryのschemaを同じstructにしたい type Item struct { ID string `json:"id" bigquery:"id",` Data string `json:"data" bigquery:"data"` Timestamp time.Time `json:"time_stamp" bigquery:"timestamp"` }
ただし、nullableにできない(requiredになってしまう)という事に悩んだため、なくなく他の方法を探してみたという感じでした。
参照
試したコードスニペットと参考にした公式です。
おわりに
InferSchemaでNullalbeを指定する方法がわかったら知りたい...!!