S3からデータを抽出できるAWS Athena(アテナと読みます)。 サービス開始当初はJavaでないと使用できなかったのですが、いつの間にかJavascript SDKが公開されています。 ブラウザから直接クエリが投げられ、サーバー側の実装が一切不要なため是非おすすめしたいサービスです。 当記事ではブラウザからクエリを投げてみるところまで、行ってみます。
SDKの入手
次のサイトからSDKを入手してください。 AWS SDK for JavaScript のドキュメント
リストの中からAthenaを選んでダウンロードします。
S3にデータを用意します。
Data1.json
{ "id": 1, "name": "name1" } { "id": 2, "name": "name2" } { "id": 3, "name": "name3" }
Data2.json
{ "id": 4, "name": "name4" } { "id": 5, "name": "name5" }
Athenaでテーブル定義を作ります。
DB名、テーブル名、S3上のKEY(フォルダ名)を設定します。 KEYは最後"/"スラッシュで終わる必要があるので注意してください。
JSONの内容に合わせて列名と型を入れます。型が違うとSQL実行時にエラーになるのできちんと設定してください。
パーティションというRDBでいう所のINDEXに近い物を設定できますが、今回はパスしておきます。
これでテーブルが完成しました。
試しに実行してみましょう。
きちんとJSONの中が取れてるのが確認できました。これをHTMLから実行してみます。
IAMの用意
細かい手順は省きますが、"AmazonAthenaFullAccess"というポリシーがあるので、これをアタッチしたユーザーを作っておけば大丈夫です。
また、アクセスキーを作成して置いてください。あとでHTMLに埋め込みます。
今回はアクセスキーをHTMLへ埋め込みますが、サービスを本稼働させる場合はセキュリティー上の問題があります。
AWS STSで一時キーを発行するなど、別の手段でアクセスキーの発行を検討してください。
HTMLの用意
いよいよHTMLからAthenaを呼び出していきます。
次のファイルを作成してください。
athena.html
<!doctype htm> <html> <head> <script src="aws-sdk-2.224.1.min.js"></script> <script> var athena = new AWS.Athena({ accessKeyId: '<IAMのアクセスキーのAccess Key Id>', secretAccessKey: '<IAMのアクセスキーのSecret Access Key>', region: 'ap-northeast-1' }); function startQueryExecution(callback) { var params = { QueryString: 'SELECT * FROM "xpyama"."table1" limit 10', ResultConfiguration: { OutputLocation: 's3://<バケット名>/athena/table1_result' } }; athena.startQueryExecution(params, function(err, data) { if (err) { console.log(err); return; } callback(data.QueryExecutionId); }); } function getQueryExecution(queryExecutionId, callback) { var params = { QueryExecutionId: queryExecutionId }; athena.getQueryExecution(params, function(err, data) { if (err) { console.log(err); return; } if (data.QueryExecution.Status.State == 'RUNNING') { getQueryExecution(queryExecutionId, callback); return; } callback(); }); } function getQueryResults(queryExecutionId, callback) { var params = { QueryExecutionId: queryExecutionId }; athena.getQueryResults(params, function(err, data) { if (err) { console.log(err); return; } callback(data); }); } function showData(data) { var table = '<table>'; for (rowNo in data.ResultSet.Rows) { table += '<tr>'; for (colNo in data.ResultSet.Rows[rowNo].Data) { table += '<td>'; table += data.ResultSet.Rows[rowNo].Data[colNo].VarCharValue; table += '</td>'; } table += '</tr>'; } table += '</table>'; document.getElementsByTagName('body')[0].innerHTML = table; } startQueryExecution(function(queryExecutionId) { getQueryExecution(queryExecutionId, function() { getQueryResults(queryExecutionId, function(data) { showData(data); }); }); }); </script> </head> <body> </body> </html>
ブラウザで開くとデータが取得できることが確認できます。
Javascriptの解説
19行目:startQueryExecution AthenaでSQLを実行します。ただし結果はすぐには返って来ず、結果確認用のIDが返ってきます。
32行目:getQueryExecution 結果確認用のIDを使い、SQLが実行し終わったかどうかを確認しています。 ステータスが"RUNNING"の場合は、まだ実行中なので再び確認しに行っています。
49行目:getQueryResults 結果確認用のIDを使い、SQLの実行結果を取得しにいきます。 実行結果はstartQueryExecutionで指定したフォルダに出力されるため、いつでも取得しなおすことができます。 古い結果が不要な場合はS3のライフサイクルを設定し、実行結果ファイルごと消してやればOKです。
58行目:showData 実行結果を画面に表示しています。
いかがだったでしょうか。
1からテーブル作ってデータ作ってとやると手間はありますが、1度構築してしまえばRDBと遜色なく使用できると思います。 SQLの実行結果が再利用できる点でも、ページングの処理やシークしながら結果取得できるので便利だと思います。 もっと複雑な機能も備わっているので、その辺りは別の機会にお伝えします。