PHPでの記事『DynamoDBのjsonサポートを試してみた。 』があったのでRubyで試してみました。
PHPの方ではSDKがまだJSONを直接扱えるようにライブラリが対応していないので、対応されているはずのRubyでどうなっているか試したメモです。
JSONサポートといっても、DynamoDB側はdata typeを増やしてJSONで必要となる型に対応しているだけで、JSONを処理しているのはSDK側ということですね。(間違ってたらご指摘を!)
結論としては先日リリースされた AWS SDK for Ruby 2 を使えばまぁ大丈夫です。AWS SDK Ruby 2 についてはAWS SDK for Ruby version2 Released!が参考になります。
Gemfile
Gemfileですが、正式リリースされたのはcoreのみのようなので、aws-sdk 全体が必要ならGemfileには
gem "aws-sdk", ">=2.0.0.pre"
を追記すればよいですが、今回はcoreだけでOKなので
gem 'aws-sdk-core', '~> 2.0'
としています。
テーブルの準備
http://aws.amazon.com/jp/blogs/aws/dynamodb-update-json-and-more/ で書かれているデータを使うことにしたので、名前が people で、person_id を Hash Key とするテーブルを作ります。
コードは以下の通り。アクセスキーは適宜修正くださいませ。。。
require 'aws-sdk-core'
dynamo_db = Aws::DynamoDB::Client.new(
:region => "ap-northeast-1",
:access_key_id => "XXXXXXXXXXXXXX",
:secret_access_key => "XXXXXXXXXXXXXXXXXXXXX"
)
resp = dynamo_db.create_table(
table_name: 'people',
key_schema: [
{
attribute_name: 'person_id',
key_type: 'HASH',
},
],
attribute_definitions: [
{
attribute_name: 'person_id',
attribute_type: 'N',
},
],
provisioned_throughput: {
read_capacity_units: 1,
write_capacity_units: 1,
},
)
puts "table: #{resp.table_description[:table_name]}"
puts "status: #{resp.table_description[:table_status]}"
JSONデータの書き込み
data.jsonを以下のように用意しておく。
{
"person_id" : 123,
"last_name" : "Barr",
"first_name" : "Jeff",
"current_city" : "Tokyo",
"next_haircut" :
{
"year" : 2014,
"month" : 10,
"day" : 30
},
"children" :
[ "SJB", "ASB", "CGB", "BGB", "GTB" ]
}
で、これを上記で用意したテーブルに入れるコードが下記。
require 'aws-sdk-core'
require 'json'
json_data = JSON.parse(File.read('data.json'))
dynamo_db = Aws::DynamoDB::Client.new(
:region => "ap-northeast-1",
:access_key_id => "XXXXXXXXXX",
:secret_access_key => "XXXXXXXXXXXXXXXXX"
)
resp = dynamo_db.put_item(
table_name: 'people',
item: {
'person_id' => json_data['person_id'],
'document' => json_data
}
)
JSONサポートのおかげで、そのまま突っ込めばよいだけですね。ラクです。
JSONデータの読み込み
上で入れたデータを取り出すコードは下記のような感じです。
require 'aws-sdk-core'
dynamo_db = Aws::DynamoDB::Client.new(
:region => "ap-northeast-1",
:access_key_id => "XXXXXXXXXXX",
:secret_access_key => "XXXXXXXXXXXXXXXXXXX"
)
resp = dynamo_db.get_item(
table_name: "people",
key: {
"person_id" => 123,
},
attributes_to_get: ["document"],
consistent_read: true,
)
resp.each do |r|
p r.item
puts
puts JSON.pretty_generate(r.item)
end
実行結果は下記の通りです。(表示の関係で折り返し入れてます)
{"document"=>{"first_name"=>"Jeff", "person_id"=>#<BigDecimal:7faa6d1edb78,'0.123E3',9(18)>,
"current_city"=>"Tokyo", "next_haircut"=>{"month"=>#<BigDecimal:7faa6d1ed830,'0.1E2',9(18)>,
"year"=>#<BigDecimal:7faa6d1ed718,'0.2014E4',9(18)>, "day"=>#<BigDecimal:7faa6d1ed600,'0.3E2',9(18)>},
"last_name"=>"Barr", "children"=>["SJB", "ASB", "CGB", "BGB", "GTB"]}}
{
"document": {
"first_name": "Jeff",
"person_id": "0.123E3",
"current_city": "Tokyo",
"next_haircut": {
"month": "0.1E2",
"year": "0.2014E4",
"day": "0.3E2"
},
"last_name": "Barr",
"children": [
"SJB",
"ASB",
"CGB",
"BGB",
"GTB"
]
}
}
DynamoDBでのNumber型がrubyのBigDecimalにマッピングされているので、そのままJSON出力すると文字列になってしまいますね。
この点だけ要注意な感じでしょうか。
やはりJSONそのまま使えるのいいですね。
Online IndexingがAvailable Soonということなので検索関連が強化されるのかな。そうするとうれしいですね。
検索条件ももう少し複雑なものができるとさらにうれしいですね。自分的に。