DynamoDBのJSONサポートをrubyで試す

PHPでの記事『[DynamoDBのjsonサポートを試してみた。](http://qiita.com/inouet/items/663fb264ab655381e4b0) 』があったので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!](http://dev.classmethod.jp/cloud/aws/aws-sdk-for-ruby-version2-released/)が参考になります。

# Gemfile

Gemfileですが、正式リリースされたのはcoreのみのようなので、aws-sdk 全体が必要ならGemfileには

```rb
gem "aws-sdk", ">=2.0.0.pre"
```

を追記すればよいですが、今回はcoreだけでOKなので

```rb
gem 'aws-sdk-core', '~> 2.0'
```

としています。


# テーブルの準備

http://aws.amazon.com/jp/blogs/aws/dynamodb-update-json-and-more/ で書かれているデータを使うことにしたので、名前が people で、person_id を Hash Key とするテーブルを作ります。

コードは以下の通り。アクセスキーは適宜修正くださいませ。。。

```rb
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を以下のように用意しておく。

```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" ]
}
```

で、これを上記で用意したテーブルに入れるコードが下記。

```rb
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データの読み込み

上で入れたデータを取り出すコードは下記のような感じです。

```rb
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
```

実行結果は下記の通りです。（表示の関係で折り返し入れてます）

```txt
{"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ということなので検索関連が強化されるのかな。そうするとうれしいですね。
検索条件ももう少し複雑なものができるとさらにうれしいですね。自分的に。