Amazon Simple Storage Service

S3 Selectを使ってCSVからデータを抽出してみた

こんにちは、Amazon Connect担当になりつつある、ディーネット山田です。

つい先日、大阪リージョンが一般向けに解禁となりましたね。

関西人からすると、(自宅環境からはまだ測定していませんが)東京リージョンより大阪リージョンの方が
レイテンシーが小さいはずなので、レイテンシーを気にするEC2とかは大阪に引っ越ししたいと思います。
(※) プロバイダーのルーティング次第なので、東京に一度行ってから大阪に来ているようならおすすめはしません。

今回は、Amazon Connect案件でも使用した、Amazon S3 Selectについて簡単に紹介したいと思います。

Amazon S3 Selectとは

S3バケット内に保存したオブジェクト(ファイル)に対して、SQL文を用いてデータを取り出すことのできるサービスになります。
例えば、S3バケットに保存したCSVファイルから電話番号をキーにして、顧客名を取り出すといったことも可能になります。
通常SQLと言ったらMySQLに代表されるようなRDB(リレーショナルデータベース)で使われることが多いですが、手軽にアップロード
できるS3で利用できるのは便利だと思います。

実際にAmazon S3 Selectを使う

CSVデータを用意する

no,facility,address
1,東京タワー,東京都港区芝公園4丁目2-8
2,東京スカイツリー,東京都墨田区押上1丁目1-2
3,株式会社ディーネット 大阪本社,大阪市中央区北浜2-6-11 北浜エクセルビル5F
4,株式会社ディーネット 東京本社,東京都港区虎ノ門2-3-22 第一秋山ビル5F
5,大阪城,大阪府大阪市中央区大阪城1-1
6,あべのハルカス,大阪府大阪市阿倍野区阿倍野筋1丁目1-43
7,ユニバーサル・スタジオ・ジャパン,大阪府大阪市此花区桜島2丁目1-33
8,東京駅,東京都千代田区丸の内1丁目
9,大阪駅,大阪府大阪市北区梅田3丁目1-1

ここでは大体皆さんがご存知の名称と住所をCSVのテーブルに表現してみました

S3バケットを作成する

S3バケットにCSVをアップロードする

S3 Selectを使って情報を取り出してみる

ちなみに、SJISだとエラーが表示されました

AWSマネジメントコンソールで使うよりコードで使うものでしょ!ということで実際にコードも紹介します

事前準備として以下は適宜対応お願いいたします

  • IAMロールやアクセスキー等の準備
  • boto3ライブラリのインストール

Python3で書いております

import boto3
import json

# バケット名とCSVファイル名を定義する
bucket = "yamada-blog-bucket"
file = "address_list.csv"
facility = "東京スカイツリー"

# S3 Selectで使用するSQLクエリを生成する
query = "SELECT * FROM S3Object s WHERE s.\"facility\" = \'{0}\' LIMIT 1".format(facility)

# boto3を使ってS3へAPI接続する
s3 = boto3.client(
    's3'
)

# S3 Selectを使ってS3上にあるCSVファイルにクエリを投げる
response = s3.select_object_content(
    Bucket=bucket,
    Key=file,
    ExpressionType='SQL',
    Expression=query,
    InputSerialization={
        'CSV': {
            'FileHeaderInfo': 'USE',
            'RecordDelimiter': '\r\n',
            'FieldDelimiter': ',',
        },
        'CompressionType': 'NONE',
    },
    OutputSerialization={
        'JSON': {
            'RecordDelimiter': '\n'
        }
    }
)

# S3 SelectからはJSON形式で応答が返ってくるのでペイロードを受け取る
s3_payload = ''
for payload in response['Payload']:
    if 'Records' in payload:
        records = payload['Records']['Payload'].decode('utf-8')
        s3_payload += records

# ペイロード有無によって分岐して、ペイロードが有る場合は、
# 住所を表示する
if s3_payload != '':
    address = json.loads(s3_payload)
    print("結果が見つかりました")
    print("{0}の住所は、{1}ですね".format(address['facility'], address['address']))
else:
    print("結果が見つかりませんでした")

結果

結果が表示されましたね。

結果が見つかりました
東京スカイツリーの住所は、東京都墨田区押上1丁目1-2ですね

ちゃんと事前に登録した住所が表示されましたね
とうきょうスカイツリー駅か押上駅が最寄りです。。。

総評

Amazon Connectで動的な処理を行わせる場合、Lambda統合によってLambdaと連携する必要がありますが、
DynamoDBによるデータ管理は操作が少し難しいし、LambdaでS3にあるCSVファイルを全て展開しコード内で
処理させるのは、メモリ消費、処理時間という意味ではあまり望ましくないのでS3 Selectをぜひ使って
みてください。

追伸

使いやすいように文字コードをUTF-8としているので、そのまま使う場合は必要に応じて元データ等を変換してください。
S3バケットにCSVが設置されたら、S3イベントでLambdaをキックして、Lambda上でSJISからUTF-8に変換してバケットに置きなおす記事は今後アップ予定です。

参考サイト

Amazon S3 Select が一般公開
Amazon S3 Select を使用して、サーバーまたはデータベースなしでデータをクエリする
Amazon S3 Select と S3 Glacier Select の SQL リファレンス

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA