S3 Selectでは、CSV, JSON(行 or ドキュメント), Parquetといったファイル形式がサポートされていますが、このうち、扱いやすさと柔軟性の高そうなJSON行について、調べてみました。
サンプルファイル
今回用意したファイルはこちら。
{ "id": "1", "name": "suzuki", "age": 20 } { "id": "2", "name": "tanaka", "birthplace": "Tokyo", "hobby": ["baseball"] } { "id": "3", "name": "yamada", "age": 25, "birthplace": "Tokyo", "hobby": ["tennis", "soccer"] } { "id": "4", "name": "sato", "birthplace": "Saitama", "hobby": ["baseball"] }
ポイントは、
- 行ごとに項目の過不足がある
- 配列型が存在
という点です。
確認はマネジメントコンソールからS3 Selectを直接実行しています(SDK経由だと、出力の形式が少し変わるかもしれません)
全件取得 : select * from s3object s
[ { "id": "1", "name": "suzuki", "age": 20 }, { "id": "2", "name": "tanaka", "birthplace": "Tokyo", "hobby": [ "baseball" ] }, { "id": "3", "name": "yamada", "age": 25, "birthplace": "Tokyo", "hobby": [ "tennis", "soccer" ] }, { "id": "4", "name": "sato", "birthplace": "Saitama", "hobby": [ "baseball" ] } ]
全件、全属性を出力。問題ありませんね。
数値型で絞り込み(結果が1件) : select * from s3object s where s.age > 20
{ "id": "3", "name": "yamada", "age": 25, "birthplace": "Tokyo", "hobby": [ "tennis", "soccer" ] }
条件を指定した場合。こちらも想定どおり。
数値型で絞り込み(結果が複数件) : select * from s3object s where s.age >= 20
[ { "id": "1", "name": "suzuki", "age": 20 }, { "id": "3", "name": "yamada", "age": 25, "birthplace": "Tokyo", "hobby": [ "tennis", "soccer" ] } ]
1つ上の結果との比較ですが、結果が1件の時はドキュメント型、複数件の時はリスト型で返るみたいですね。
配列型で絞り込み(NGな例) : select * from s3object s where s.hobby = 'baseball'
[]
配列型の項目の検索はこれではダメみたいです。
配列型で絞り込み(OKな例) : select * from s3object s where s.hobby[0] = 'baseball'
[ { "id": "2", "name": "tanaka", "birthplace": "Tokyo", "hobby": [ "baseball" ] }, { "id": "4", "name": "sato", "birthplace": "Saitama", "hobby": [ "baseball" ] } ]
配列のインデックスを指定してあげればOK。
ちなみに、存在しないインデックスを指定した場合は、エラーにはならず、空のリストが返ります。
ちなみに、インデックスを問わず、contains的な検索をしたい場合は、 'soccer' in s.hobby
と書くようです。
文字列で絞り込み(LIKE) : select * from s3object s where s.birthplace like '%o'
[ { "id": "2", "name": "tanaka", "birthplace": "Tokyo", "hobby": [ "baseball" ] }, { "id": "3", "name": "yamada", "age": 25, "birthplace": "Tokyo", "hobby": [ "tennis", "soccer" ] } ]
LIKE検索はサポートされています。
文字列で絞り込み(NOT EQUAL) : select * from s3object s where s.birthplace != 'Tokyo'
{ "id": "4", "name": "sato", "birthplace": "Saitama", "hobby": [ "baseball" ] }
birthplace項目自体が存在し、かつ、 Tokyo
以外のものが返ります。
項目が存在しないものを探す : select * from s3object s where s.birthplace IS NULL
{ "id": "1", "name": "suzuki", "age": 20 }
項目が存在しないものを取得する場合は IS NULL
でできます。
ルートレベル以外での検索 : select * from s3object[*].hobby s where s[1] = 'soccer'
{ "_1": [ "tennis", "soccer" ] }
直近でこれを駆使する機会はなさそうなので触りだけですが、詳しくは公式ドキュメントに記載されています。
まとめ
ほぼ予想どおりの動きをしてくれるみたいなので、問題なく使えそうでした。