PCがあれば何でもできる!

へっぽこアラサープログラマーが、覚えたての知識を得意げにお届けします

【Ruby】DynamoDBのJSONドキュメントを試してみた(aws-sdk v2.0.0 stable)

f:id:m_doi2:20141011115038j:plain

ついにDynamoDBがJSONドキュメントに対応されましたね!
NoSQLのAmazon DynamoDBがJSONドキュメントに対応、25GB/月間2億リクエストまで無料枠も拡大 - Publickey

記事にはJavaのサンプルしかなかったので、早速Rubyで試してみました。
今回は「aws-sdk v2.0.0 stable」を使用しています。

put_itemで登録してみる

dynamodb = Aws::DynamoDB::Client.new(
  access_key_id: '[ACCESSS_KEY]',
  secret_access_key: '[SECRET_ACCESS_KEY]',
  region: 'ap-northeast-1'
)

dynamodb.put_item(
  table_name: "Test",
  item: {
    # Hash Key
    "id" => 1,
    # JSONドキュメント保存(Hashを渡してみる)
    "json_hash" => {
      "person_id" => 123,
      "last_name" => "Barr",
      "first_name" => "Jeff",
      "current_city" => nil,
      "next_haircut" => {
        "year" => 2014,
        "month" => 10,
        "day" => 30
      },
      "children" => [ "SJB", "ASB", "CGB", "BGB", "GTB" ]
    },
    # JSONドキュメント保存(Arrayを渡してみる)
    "json_array" => [
      {
        "name" =>"bob",
        "married" => true,
        "weight" => 65.3
      },
      {
        "name" =>"tom",
        "married" => false,
        "weight" => 80.2
      },
      {
        "name" =>"michael",
        "married" => true,
        "weight" => 57.6
      }
    ]
  }
)

get_itemで登録値を確認してみる

puts dynamodb.get_item(
  table_name: "Test",
  key: {
    "id" => 1
  },
  consistent_read: true
).item.to_s

#出力結果(わかりやすいように整形しています)
=> {
  "id" => #<BigDecimal:106a756f0,'0.1E1',9(18)>
  "json_hash" => {
    "person_id" => #<BigDecimal:106a761b8,'0.123E3',9(18)>,
    "last_name" => "Barr",
    "first_name" => "Jeff",
    "current_city" => nil,
    "next_haircut" => {
      "year" => #<BigDecimal:106a75dd0,'0.2014E4',9(18)>,
      "month" => #<BigDecimal:106a75ec0,'0.1E2',9(18)>,
      "day" => #<BigDecimal:106a75cb8,'0.3E2',9(18)>
    },
    "children" => [ "SJB", "ASB", "CGB", "BGB", "GTB" ]
  },
  "json_array" => [
    {
      "name" =>"bob",
      "married" => true,
      "weight" => #<BigDecimal:106a76d48,'0.653E2',18(18)>
    },
    {
      "name" =>"tom",
      "married" => false,
      "weight" => #<BigDecimal:106a76a28,'0.802E2',18(18)>
    },
    {
      "name" =>"michael",
      "married" => true,
      "weight" => #<BigDecimal:106a76708,'0.576E2',18(18)>
    }
  ]
}

ばっちり、HashとArrayで返ってきましたぞ Σ(・ω・ノ)ノ
文字列、真偽値、整数、小数、nullも問題なく扱え、整数と小数はBigDecimalに格納してくれるようです。

もうっ、便利すぎるよ!
※おまけに、aws-sdkはv1しか使ったことなかったので、v2の仕様のシンプルさに感動中(´;ω;`)

update_itemで更新してみる

update_item(attribute_updates:PUT)

attribute_updatesオプションでaction: PUTを指定すると、以下のようにHashとArrayそのものがごっそり置き換わります。

dynamodb.update_item(
  table_name: "Test",
  key: { "id" => 1 },
  attribute_updates: {
    "json_hash" => {
      value: {
        "test" => "a"
      },
      action: "PUT"
    },
    "json_array" => {
      value: [
        {
          "name" =>"emily",
          "married" => false,
          "weight" => 48.1
        }
      ],
      action: "PUT"
    }
  }
)

#get_itemでの取得結果(わかりやすいように整形しています)
=> {
  "id" => #<BigDecimal:105ef4f60,'0.1E1',9(18)>,
  "json_hash" => {
    "test"=>"a"
  },
  "json_array" => [
    {
      "name"=>"emily",
      "married"=>false,
      "weight" => #<BigDecimal:105ef5528,'0.481E2',18(18)>
    }
  ] 
}

update_item(attribute_updates:ADD)

attribute_updatesオプションでaction: ADDを指定した場合、Hashに対して実行しようとすると以下のエラーが発生します。

`call': One or more parameter values were invalid: ADD action is not supported for the type M (Aws::DynamoDB::Errors::ValidationException)

ArrayにADDした場合は、終端に要素が追加されます。

dynamodb.update_item(
  table_name: "Test",
  key: { "id" => 1 },
  attribute_updates: {
    "json_array" => {
      value: [
        {
          "name" =>"emily",
          "married" => false,
          "weight" => 48.1
        }
      ],
      action: "ADD"
    }
  }
)

#get_itemでの取得結果(json_arrayのみ)(わかりやすいように整形しています)
=> "json_array" => [
  {
    "name" =>"bob",
    "married" => true,
    "weight" => #<BigDecimal:106a76d48,'0.653E2',18(18)>
  },
  {
    "name" =>"tom",
    "married" => false,
    "weight" => #<BigDecimal:106a76a28,'0.802E2',18(18)>
  },
  {
    "name" =>"michael",
    "married" => true,
    "weight" => #<BigDecimal:106a76708,'0.576E2',18(18)>
  },
  {
    "name" =>"emily",
    "married" => false,
    "weight" => #<BigDecimal:106a76528,'0.481E2',18(18)>
  }
]

update_item(attribute_updates:DELETE)

attribute_updatesオプションのaction: DELETEは、Hash、Arrayともに未対応のようです。

■Hashのエラー

`call': One or more parameter values were invalid: DELETE action with value is not supported for the type M (Aws::DynamoDB::Errors::ValidationException)

■Arrayのエラー

`call': One or more parameter values were invalid: DELETE action with value is not supported for the type L (Aws::DynamoDB::Errors::ValidationException)

update_item (update_expression)

前述の通り、attribute_updatesではJSON内の要素を細かく編集することができません。そういった場合は、update_expressionを使用すると良さそうです。

# 特定の要素を書き換え
dynamodb.update_item(
  table_name: "Test",
  key: { "id" => 1 },
  update_expression: "SET json_hash.current_city = :city",
  expression_attribute_values: {
    ":city" => "Osaka"
  },
)
# 特定の要素を削除
dynamodb.update_item(
  table_name: "Test",
  key: { "id" => 1 },
  update_expression: "REMOVE json_hash.last_name"
)

ただ、update_expressionに複数属性分の処理を記述する方法がわからなかったです。

登録容量

1アイテムの容量は400kbまでです。調子に乗り過ぎて膨大なデータを保存しちゃうと、以下のエラーがでますのでご注意を。

`call': Item size has exceeded the maximum allowed size (Aws::DynamoDB::Errors::ValidationException)

空文字の値を含んだJSONを登録しようとするとエラーになる

たまたま気づいたのですが、例えば以下の様な空文字の値を含んだHashまたはArrayを登録しようとすると、エラーになります。スペースを入れるか、nullを指定するのが良いでしょう。

{ "test" => "" }

`call': One or more parameter values were invalid: An AttributeValue may not contain an empty string (Aws::DynamoDB::Errors::ValidationException)

対応リージョン

現在JSONドキュメントに対応しているリージョンは、

  • AmazonのUS East (北バージニア)
  • US West(オレゴン)
  • Asia Pacific(東京)
  • EU(アイルランド)

のみです。昨夜、それに気づかずに、はまっちゃいました orz

未対応リージョンでJSONドキュメントを使用しようとすると、以下のエラーでます。

`call': Supplied AttributeValue is empty, must contain exactly one of the supported datatypes (Aws::DynamoDB::Errors::ValidationException)

 
 
やっつけですが、以上になります!良きDynamoライフを!