この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部、池田です。
BigQueryのJSON型は申請が必要な プレビュー
という認識だったのですが、いつの間にか普通に使えるようになっていました!
(某所にも確認しましたが、GA(一般提供)という扱いで良いそうです。
以下の公式ガイドにもプレビューの記述はありません!)
【 Working with JSON data in Google Standard SQL 】
Amazon Redshift だと SUPER タイプ 、 Snowflake だと VARIANT などが近いかと思います。
STRUCT型 に比べて、スキーマオンリード的に、より柔軟に値を格納できます。
使ってみる
軽く使ってみます。
JSONリテラル
は以下のような構文です。
JSON <JSONの文字列>
リファレンスの例を元に、簡単なSELECT文を動かしてみます。
-- CREATE TABLE my_json.verify AS
WITH sample_table AS (
SELECT JSON """{
"id": 10,
"type": "fruit",
"name": "apple",
"on_menu": true,
"recipes":
{
"salads":
[
{ "id": 2001, "type": "Walnut Apple Salad" },
{ "id": 2002, "type": "Apple Spinach Salad" }
],
"desserts":
[
{ "id": 3001, "type": "Apple Pie" },
{ "id": 3002, "type": "Apple Scones" },
{ "id": 3003, "type": "Apple Crumble" }
]
}
}""" AS json_col
)
SELECT json_col, json_col.id, json_col.recipes.salads FROM sample_table;
ドットで簡単に各要素へアクセスできていますね。
ちなみに、前述のSELECT文をCTASでテーブルにしてみると…
全てJSON型になっていました。
適切に扱うには適宜キャストが必要そうです。
…
SELECT json_col, INT64(json_col.id), json_col.recipes.salads FROM sample_table;
nullが特殊
冒頭の公式ガイド で気になった記述が以下です。
The JSON type has a special null value that is different from the SQL NULL. A JSON null is not treated as a SQL NULL value, …
SELECT
JSON 'null' IS NULL AS a,
JSON_VALUE(JSON 'null') IS NULL AS b;
-- a b
-- false true
null
の扱いには注意が必要そうです。
BigQuery subscriptions
以前ブログにしたBigQuery subscriptions(
Cloud Pub/Sub
からBigQueryへ直接データを投入する機能)でもメッセージをJSON型として格納できるようになりました。
【 Pub/Sub release notes > November 15, 2022 】
簡単に動かしてみます。 詳細は以前のブログをご覧下さい。
以前は( トピック スキーマ
を使わずに)メッセージを受け取るのは data
というSTRING型のカラムである必要がありました。
CREATE TABLE subscriptions.sample_with_meta (
subscription_name STRING,
message_id STRING,
publish_time TIMESTAMP,
data STRING,
attributes STRING
)
PARTITION BY DATE(publish_time);
↓↓↓↓↓↓↓↓
JSON型で受け取れます!
CREATE TABLE subscriptions.sample_with_meta_json (
subscription_name STRING,
message_id STRING,
publish_time TIMESTAMP,
data JSON,
attributes STRING
)
PARTITION BY DATE(publish_time);
※↑では直し忘れたのですが、 attributes
カラムもJSON型で受け取れます。
一般に公開されているPub/Subのトピック をサブスクライブ登録します。
gcloud pubsub subscriptions create sample-with-meta-json-sub \
--topic=projects/pubsub-public-data/topics/taxirides-realtime \
--bigquery-table=my-project.subscriptions.sample_with_meta_json \
--write-metadata
データが格納されます。(↓画像は左が以前のもの、右が今回のもの。)
見た目ではSTRING型と区別がつかないです…
要素へのアクセス
以前は以下のように要素にアクセスして、ビューにしていました。
STRING型のdataカラム
CREATE VIEW subscriptions.sample_view AS
SELECT
JSON_VALUE(data, '$.ride_id') AS ride_id,
SAFE_CAST(JSON_VALUE(data, '$.point_idx') AS INT64) AS point_idx,
SAFE_CAST(JSON_VALUE(data, '$.latitude') AS BIGNUMERIC) AS latitude,
SAFE_CAST(JSON_VALUE(data, '$.longitude') AS BIGNUMERIC) AS longitude,
SAFE_CAST(JSON_VALUE(data, '$.timestamp') AS TIMESTAMP) AS timestamp,
SAFE_CAST(JSON_VALUE(data, '$.meter_reading') AS NUMERIC) AS meter_reading,
SAFE_CAST(JSON_VALUE(data, '$.meter_increment') AS NUMERIC) AS meter_increment,
JSON_VALUE(data, '$.ride_status') AS ride_status,
SAFE_CAST(JSON_VALUE(data, '$.passenger_count') AS INT64) AS passenger_count
FROM
subscriptions.sample_with_meta
WHERE
DATE(publish_time) >= CURRENT_DATE()
;
※ JSON_VALUE() はSTRING型もJSON型も受け取れるので、実はこのアクセス方法もそのまま使えます。
↓↓↓↓↓↓↓↓
JSON型のdataカラム
CREATE VIEW subscriptions.sample_view_json AS
SELECT
data.ride_id,
data.point_idx,
data.latitude,
data.longitude,
data.timestamp,
data.meter_reading,
data.meter_increment,
data.ride_status,
data.passenger_count
FROM
subscriptions.sample_with_meta_json
WHERE
DATE(publish_time) >= CURRENT_DATE()
;
だいぶシンプルに要素にアクセスできるようになりました。 (分かりやすくするためキャストは省略しました。)
おわりに
ずっと待っていました。