はじめに
BigQueryにbqコマンドでテーブル作成・データ投入・スキーマ変更する。 ネストされたデータも扱いたいので、今回はjsonファイルを読み込むようにする CSVは現段階でネストされたデータのimportをサポートされていない
CSV ファイルはネストされたデータや繰り返しデータに対応していません。
https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv ちょうどいいサンプルデータ( https://gist.github.com/isdyy/5072792 )を置いてくださる方がいたので、それを拝借。
準備
https://gist.github.com/isdyy/5072792 にあるように2つのデータを用意する。1つはスキーマ。もう1つはデータ
- スキーマ
[ { "name": "kind", "type": "string" }, { "name": "fullName", "type": "string" }, { "name": "age", "type": "integer" }, { "name": "gender", "type": "string" }, { "name": "citiesLived", "type": "record", "mode": "repeated", "fields": [ { "name": "place", "type": "string" }, { "name": "numberOfYears", "type": "integer" } ] }, { "name": "note", "type": "string" } ]
- データ
{"gender": "Male", "fullName": "John Doe", "age": 22, "citiesLived": [{"numberOfYears": 5, "place": "Seattle"}, {"numberOfYears": 6, "place": "Stockholm"}], "kind": "person"} {"gender": "Female", "fullName": "Jane Austen", "age": 24, "citiesLived": [{"numberOfYears": 2, "place": "Los Angeles"}, {"numberOfYears": 2, "place": "Tokyo"}], "kind": "person"} {"note": "with newline (\\n)", "kind": "person", "gender": "Male", "age": 30, "fullName": "newline", "citiesLived": [{"place": "Shinjuku-ku,\nTokyo"}]} {"note": "with tab (\\t)", "age": 30, "fullName": "tab", "citiesLived": [{"place": "Shinjuku-ku,\tTokyo"}], "kind": "person"} {"note": "japanese / unicode escape sequence", "gender": "Female", "citiesLived": [{"place": "\u6a2a\u6d5c\u5e02"}], "fullName": "\u6a2a\u6d5c \u82b1\u5b50 (1)", "kind": "person"} {"note": "japanese / raw utf-8", "gender": "Female", "citiesLived": [{"place": "横浜市"}], "fullName": "横浜 花子 (2)", "kind": "person"} {"note": "double-quoted string", "fullName": "\"quoted\"", "kind": "person"}
テーブルのみ作成
# bq mk --table logs.sample nested01.fields.json Table '****:logs.sample' successfully created.
ブラウザ上で以下の通り作成されている また、bq showコマンドでスキーマを確認できる
# bq show logs.sample Table ****:logs.sample Last modified Schema Total Rows Total Bytes Expiration Time Partitioning Labels ----------------- ----------------------------------- ------------ ------------- ------------ ------------------- -------- 19 Nov 21:09:54 |- kind: string 0 0 |- fullName: string |- age: integer |- gender: string +- citiesLived: record (repeated) | |- place: string | |- numberOfYears: integer |- note: string
データの投入
# bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json Upload complete. Waiting on bqjob_r4b711f3cb6f6854b_000001672be52e12_1 ... (0s) Current status: DONE
無事投入された。適切にネストもされている。
テーブル作成+データ投入
スキーマ作成と同時に、データの投入も可能
# bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json nested01.fields.json Upload complete. Waiting on bqjob_r49704f78c779ebd5_000001672bd96baa_1 ... (0s) Current status: DONE
もちろん結果は同じ
データのみをつかって、テーブルを自動作成
“` –autodetect “` オプションを使う。
# bq load --source_format=NEWLINE_DELIMITED_JSON --autodetect logs.sample nested01.data.json Upload complete. Waiting on bqjob_r49704f78c779ebd115_00001672bd96baa_1 ... (0s) Current status: DONE
スキーマを変更する
nested01.fields.jsonを以下の通り変更
[ { "name": "kind", "type": "string" }, { "name": "fullName", "type": "string" }, { "name": "age", "type": "integer" }, { "name": "gender", "type": "string" }, { "name": "country", "type": "string" }, { "name": "company", "type": "string" }, { "name": "citiesLived", "type": "record", "mode": "repeated", "fields": [ { "name": "place", "type": "string" }, { "name": "numberOfYears", "type": "integer" } ] }, { "name": "note", "type": "string" } ]
# bq update logs.sample nested01.fields.json Table '****:logs.sample' successfully updated.
スキーマが追加。 今まで投入されていたデータに追加されたカラムはnullが入る。
新しいスキーマに、旧データを投入
(スキーマは変更したが、投入するデータは以前と同じ)
# bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json Upload complete. Waiting on bqjob_r73583e1d3c68485e_000001672bece222_1 ... (0s) Current status: DONE
エラーにはならず、単純に新しいスキーマにはnullが入る
新スキーマに沿ったデータを投入
{"gender": "Male", "fullName": "John Doe", "age": 22, "citiesLived": [{"numberOfYears": 5, "place": "Seattle"}, {"numberOfYears": 6, "place": "Stockholm"}], "kind": "person", "country": "Japan", "company": "A company"} {"gender": "Female", "fullName": "Jane Austen", "age": 24, "citiesLived": [{"numberOfYears": 2, "place": "Los Angeles"}, {"numberOfYears": 2, "place": "Tokyo"}], "kind": "person", "country": "USA", "company": "B company"} {"note": "with newline (\\n)", "kind": "person", "gender": "Male", "age": 30, "fullName": "newline", "citiesLived": [{"place": "Shinjuku-ku,\nTokyo"}], "country": "Japan", "company": "A company"} {"note": "with tab (\\t)", "age": 30, "fullName": "tab", "citiesLived": [{"place": "Shinjuku-ku,\tTokyo"}], "kind": "person", "country": "USA", "company": "B company"} {"note": "japanese / unicode escape sequence", "gender": "Female", "citiesLived": [{"place": "\u6a2a\u6d5c\u5e02"}], "fullName": "\u6a2a\u6d5c \u82b1\u5b50 (1)", "kind": "person", "country": "Japan", "company": "A company"} {"note": "double-quoted string", "fullName": "\"quoted\"", "kind": "person"}
# bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json Upload complete. Waiting on bqjob_r34be71bb151950ee_000001672bf33c1d_1 ... (0s) Current status: DONE
投入された
テーブル作成
jsonファイルを作成する
[ { "name": "register_day", "type": "STRING" }, { "name": "rtime", "type": "STRING" }, { "name": "tid", "type": "INTEGER" }, { "name": "sid", "type": "INTEGER" }, { "name": "flag", "type": "INTEGER" }, { "name": "id", "type": "INTEGER" }, { "name": "lesson_date", "type": "TIMESTAMP" } ]
jsonファイルを用意して、bqコマンドで作成する
bq mk --table --expiration 3600 --description "This is my table" --label organization:development logs.mytable testTable.json
Table ‘***:logs.mytable’ successfully created. と表示されたら成功。 ブラウザで確認すると、問題なく作成されている。
スキーマ変更
[ { "name": "register_day", "type": "STRING" }, { "name": "rtime", "type": "STRING" }, { "name": "tid", "type": "INTEGER" }, { "name": "sid", "type": "INTEGER" }, { "name": "flag", "type": "INTEGER" }, { "name": "id", "type": "INTEGER" }, { "name": "lesson_date", "type": "TIMESTAMP" }, { "name": "lesson_date2", "type": "TIMESTAMP" } ]
lesson_date2を追加し、bq update コマンドを実施
bq update logs.mytable testTable.json
Table ‘****:logs.mytable’ successfully updated.
となれば成功 無事カラムが追加された
テーブル定義をdumpする
bq --format=prettyjson show --schema tsukadaproject:logs.logsPartition > bbbb
[ { "mode": "NULLABLE", "name": "register_day", "type": "STRING" }, { "mode": "NULLABLE", "name": "rtime", "type": "STRING" }, { "mode": "NULLABLE", "name": "lesson_date", "type": "TIMESTAMP" } ]
当然このformatを読み込ませることができる
bq mk --table --expiration 3600 --description "This is my table" --label organization:development logs.bbbb bbbb
パーティションテーブルを作成する
JSONはスキーマ情報のみ。パーティションテーブルの指定はbqコマンドのオプションで行う。
[ { "mode": "NULLABLE", "name": "register_day", "type": "STRING" }, { "mode": "NULLABLE", "name": "rtime", "type": "STRING" }, { "mode": "NULLABLE", "name": "lesson_date", "type": "TIMESTAMP" } ]
パーテョションテーブル作成
bq mk --table --expiration 3600 --description "This is my table" --time_partitioning_field=lesson_date --time_partitioning_type=DAY --label organization:development logs.cccc cccc
Table ‘****:logs.cccc’ successfully created.
参考情報
ストーリー仕立てで分かりやすくまとまっているのでおすすめ。