0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWSのS3 Selectを使ってみた

Last updated at Posted at 2023-07-08

S3でSQL文が使えるんですね。知らなかったです。
さっそく使ってみました。

入力となるJSONファイルはS3上にこんな感じである前提です。

test/data.json
{
	"info": "This is sample",
	"data_list": [
		{
			"x": 1,
			"value": 11,
			"comment": "comment 1-1"
		},
		{
			"x": 1,
			"value": 12,
			"comment": "comment 1-2"
		},
		{
			"x": 2,
			"value": "21",
			"comment": "comment 2-1"
		},
		{
			"x": 2,
			"value": 22,
			"comment": "comment 2-2"
		}
	]
}

そして、コードです。

var AWS = require('aws-sdk');
AWS.config.update({
  region: "ap-northeast-1",
});
var s3  = new AWS.S3({
});

const S3SELECT_DELIMITER = '\n';

const sql = 'SELECT * FROM s3object[*].data_list[*] AS s';

	const params = {
		Bucket: 'bucket-test',
		Key: 'test/data.json',
		ExpressionType: 'SQL',
		Expression: sql,
		InputSerialization: {
			JSON: {
				Type: "DOCUMENT"
			}
		},
		OutputSerialization: {
			JSON: {
				RecordDelimiter: S3SELECT_DELIMITER
			}
		}
	};

	var result = await s3.selectObjectContent(params).promise();
	console.log(result);

	const events = result.Payload;
	let list = [];
	for await (const chunk of events) {
		if( chunk.Records){
			var t1 = chunk.Records.Payload;
			var t2 = t1.toString();
			var t3 = t2.split(S3SELECT_DELIMITER);
			for( const item of t3){
				if( item )
					list.push(JSON.parse(item));
			}	
		}
	}
	console.log(JSON.stringify(list, null, '\t'));

結果は以下のように出力されます。

[
	{
		"x": 1,
		"value": 11,
		"comment": "comment 1-1"
	},
	{
		"x": 1,
		"value": 12,
		"comment": "comment 1-2"
	},
	{
		"x": 2,
		"value": "21",
		"comment": "comment 2-1"
	},
	{
		"x": 2,
		"value": 22,
		"comment": "comment 2-2"
	}
]

後処理の部分がわかりにくいかもしれませんが、result.Payloadは、Readable Streamです。

以下の部分がSQL文に相当します。JSONの中のdata_listをSQLの対象にしています。

const sql = 'SELECT * FROM s3object[*].data_list[*] AS s';

また、一番やりたかった出力をフィルタリングしたい場合は、例えば以下のように書き換えると

const sql = 'SELECT s.x, s.value FROM s3object[*].data_list[*] AS s WHERE s.x = 1';

以下のような出力となります。

[
	{
		"x": 1,
		"value": 11
	},
	{
		"x": 1,
		"value": 12
	}
]

ちなみに、今回は入力ファイルがJSONの場合でしたが、もしJSON Linesの場合は、以下の部分を

			JSON: {
				Type: "DOCUMENT"
			}

以下のように変えます。

			JSON: {
				Type: "LINES"
			}

入力ファイルとしてCSVの場合が多いかもしれませんが、詳細は以下ご参照ください。

(参考)
 https://aws.amazon.com/jp/blogs/developer/introducing-support-for-amazon-s3-select-in-the-aws-sdk-for-javascript/
 https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#selectObjectContent-property

ちなみに、ちゃんとMINIOでも動いてくれますよっ

おわりに

うーん、ルートが配列のJsonファイルはダメっぽいなあ

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?