ようへいの日々精進XP

よかろうもん

ダイナミック!ダイナモー(DynamoDB tutorial)vol.2 〜 JSON サポートの動作確認 〜

tl;dr

aws.typepad.com

JSONフォーマットのドキュメントをそのままDynamoDBの1アイテムとして保存できるようになりました(後述の新たなサイズ上限である400KB以内が条件)

とのことなので JSON フォーマットをドキュメントとして登録してみる動作確認。


参考


メモ

動作確認環境

  • 引き続き、そらまめ君のデータを利用させて頂く
  • Mac OSX
% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11
BuildVersion:   15A278b
  • AWS SDK for Ruby を利用(aws-sdk (2.1.20))
  • DynamoDB は DynamoDB Local を利用する。

テーブルの作成

以下のようにテーブルを作成する。

def create_table(table_name)
  table = $client.create_table({
    table_name: table_name ,
    key_schema:[
      {
        attribute_name: "mon_st_code",
        key_type: "HASH"
      },
      {
        attribute_name: "CHECK_DATE_TIME",
        key_type: "RANGE"
      },
    ],
    attribute_definitions: [
      {
        attribute_name: "CHECK_DATE_TIME",
        attribute_type: "S",
      },
      {
        attribute_name: "mon_st_code",
        attribute_type: "S",
      },
    ],
    provisioned_throughput: {
      read_capacity_units: 1,
      write_capacity_units: 1,
    },
  })
end

Hash + Range キータイプのテーブルを作成し、以下のようなハッシュデータが投入されることを想定する。

{"CHECK_DATE_TIME"=>"2015-09-15 19:00:00", "CHECK_TIME"=>"19", "mon_st_code"=>"40131030", "town_name"=>"福岡市東区", "mon_st_name"=>"香椎", "SO2"=>"NANA", "NO"=>"0", "NO2"=>"0.011", "NOX"=>"0.011", "CO"=>"NANA", "OX"=>"0.042", "NMHC"=>"0.23", "CH4"=>"1.93", "THC"=>"2.16", "SPM"=>"0.026", "PM2.5"=>"23", "SP"=>"NANA", "WD"=>"北北東", "WS"=>"3.1", "TEMP"=>"NANA", "HUM"=>"NANA", "mon_st_kind"=>"一般局"}

データの投入

データ投入時に以下のようにキーとなる mon_st_codeCHECK_DATE_TIME のみアトリビュートを指定してデータを投入する。

(snip)
#
# そらまめ君から取得したデータを解析して post_to_dynamodb メソッドを呼び出す
#
header = ['CHECK_DATE_TIME','CHECK_TIME','mon_st_code','town_name', 'mon_st_name', 'SO2','NO','NO2','NOX','CO','OX','NMHC','CH4','THC','SPM','PM2.5','SP','WD','WS','TEMP','HUM','mon_st_kind']
doc = Nokogiri::HTML.parse(html, nil, charset)
doc.xpath('//tr[td]').each do |tr|  row = tr.xpath('td').map { |td| td.content.gsub(/[\u00A0\n]|\-\-\-/,'NA') }
  row.unshift(check_time)
  row.unshift(check_date_time)  ary = [header,row].transpose
  h = Hash[*ary.flatten]
  post_to_dynamodb('soramame', h)
end

#
# 実際に DynamoDB にデータを投入するメソッド
#
def post_to_dynamodb(table, data)  
  result = $client.put_item(
    table_name: table,    
    item: {
      'mon_st_code' => data['mon_st_code'],
      'CHECK_DATE_TIME' => data['CHECK_DATE_TIME'],
      'document' => data.to_json
    }
  )
end

document キーに対して JSON ドキュメントを投入している。

データの確認

単純にクエリを投げてみる。

codes = ['42213010', '40131030']
codes.each do |code|
  query_item('soramame', code, '2015-03-12')
end

def query_item(table_name, mon_st_code, check_date_time, limit_num=1)
  result = $client.query({
    table_name: table_name, 
    select: "ALL_ATTRIBUTES",
    key_condition_expression: "mon_st_code = :v_mon_st_code and CHECK_DATE_TIME >= :v_check_date_time",
    expression_attribute_values: {
      ":v_mon_st_code" => mon_st_code,
      ":v_check_date_time" => check_date_time,
    },
  })
  result.items.each do |item|    
    puts item
  end
end

以下のように出力される。

{"CHECK_DATE_TIME"=>"2015-09-15 19:00:00", "mon_st_code"=>"42213010", "document"=>"{\"CHECK_DATE_TIME\":\"2015-09-15 19:00:00\",\"CHECK_TIME\":\"19\",\"mon_st_code\":\"42213010\",\"town_name\":\"雲仙市\",\"mon_st_name\":\"小浜大気測定局\",\"SO2\":\"0.002\",\"NO\":\"0\",\"NO2\":\"0.004\",\"NOX\":\"0.004\",\"CO\":\"NANA\",\"OX\":\"0.032\",\"NMHC\":\"NANA\",\"CH4\":\"NANA\",\"THC\":\"NANA\",\"SPM\":\"0.040\",\"PM2.5\":\"25\",\"SP\":\"NANA\",\"WD\":\"NANA\",\"WS\":\"NANA\",\"TEMP\":\"NANA\",\"HUM\":\"NANA\",\"mon_st_kind\":\"一般
局\"}"}
{"CHECK_DATE_TIME"=>"2015-09-15 19:00:00", "mon_st_code"=>"40131030", "document"=>"{\"CHECK_DATE_TIME\":\"2015-09-15 19:00:00\",\"CHECK_TIME\":\"19\",\"mon_st_code\":\"40131030\",\"town_name\":\"福岡市東区\",\"mon_st_name\":\"香椎\",\"SO2\":\"NANA\",\"NO\":\"0\",\"NO2\":\"0.011\",\"NOX\":\"0.011\",\"CO\":\"NANA\",\"OX\":\"0.042\",\"NMHC\":\"0.23\",\"CH4\":\"1.93\",\"THC\":\"2.16\",\"SPM\":\"0.026\",\"PM2.5\":\"23\",\"SP\":\"NANA\",\"WD\":\"北北東\",\"WS\":\"3.1\",\"TEMP\":\"NANA\",\"HUM\":\"NANA\",\"mon_st_kind\":\"一般局\"}"

document キーに JSON ドキュメントが登録されていることが判る。尚、このドキュメントから例えば PM2.5 の値を取り出す場合には JSON を解析する必要がある。

require 'json'

result.items.each do |item|
  parsed_item = JSON.parse(item['document'])
  puts "PM2.5:  #{parsed_item['PM2.5'].to_f}" 
end

以下のように出力される。

% ./query-item.rb
観測地: 小浜大気測定局 / PM2.5:  25.0
観測地: 香椎 / PM2.5:  23.0

尚、福岡県では以下のような基準を設けて注意喚起を行っている。

平成25年3月9日より、PM2.5の濃度が、暫定的な指針値である日平均値70μg/m3を超えると予測される場合に注意喚起を行うこととしました。

ということでひとまず香椎あたりは安心。


ということで

DynamoDB の JSON ドキュメントサポート、DynamoDB のドキュメントとして JSON ドキュメントを登録出来ることは確認出来た。但し、登録出来るということだけで、JSON を解析するアクションはアプリケーション側で実装する必要があるので頑張りましょう。ユースケースについてはパッと思いつかないが、400 KB 以下であれば雑に JSON を放り込んでおけるという点では便利だと思った。