Amazon DynamoDBをrubyで触ってみる 第2弾〜update_item〜
前回に引き続きDynamoDBをrubyでゴニョゴニョしてみました。
今回は、ドキュメントを読んで(個人的に)わかりづらかったupdate_itemについてです。
update_itemというのは、その名の通り「すでに登録してあるアイテムに変更を加える操作」です。
オプションに、PUT・ADD・DELETEというのを指定するのですが、その使い分けをまとめてみました。
まず、アトリビュート(カラムに相当)の型の種類を理解しておく必要があります。
全部で6種類あります。
タイプ | 説明 |
---|---|
N | 数字 |
S | 文字列 |
B | バイナリ |
NS | 数字の配列 |
SS | 文字列の配列 |
BS | バイナリの配列 |
続いて、PUT,ADD,DELETEの違いについてです。
PUT | 問答無用でそのアトリビュートを置き換え。存在しなければアトリビュートごと作る |
ADD | 型がNのときは、足し算。型がセット(NS,SS,BS)のときは、配列に追加 |
DELETE | 型がN,S,Bのときは、そのアトリビュートを削除。セットのときは、その要素のみを削除 |
となります。
それでは実際に試してみたいと思います。
まずはテーブルを作ってアイテムを保存します。
require 'rubygems' require 'aws-sdk' require './init.rb' dynamoClient = AWS::DynamoDB::Client.new({ :dynamo_db_endpoint => 'dynamodb.ap-northeast-1.amazonaws.com', :access_key_id => ACCESS, :secret_access_key => SECRET}) dynamoClient.create_table( :table_name => TABLE, :key_schema => {:hash_key_element => {:attribute_name => "id", :attribute_type => "N"}}, :provisioned_throughput => {:read_capacity_units => 2, :write_capacity_units => 2} ) sleep 20 dynamoClient.put_item( :table_name => TABLE, :item => { "id" => {:n => "1"}, "put" => {:n => "1"}, "add" => {:n => "1"}, "delete" => {:n => "1"} } ) dynamoClient.put_item( :table_name => TABLE, :item => { "id" => {:n => "2"}, "put" => {:ns => ["1","2","3"]}, "add" => {:ns => ["1","2","3"]}, "delete" => {:ns => ["1","2","3"]} } )
続いて、アップデートを実行します。
require 'rubygems' require 'aws-sdk' require './init.rb' dynamoClient = AWS::DynamoDB::Client.new({ :dynamo_db_endpoint => 'dynamodb.ap-northeast-1.amazonaws.com', :access_key_id => ACCESS, :secret_access_key => SECRET}) init = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} } ) p init #PUT dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} }, :attribute_updates => { "put" => { :value => {:n => "100"}, :action => "PUT" } }, ) put = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} } ) p put #ADD dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} }, :attribute_updates => { "add" => { :value => {:n => "100"}, :action => "ADD" } }, ) add = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} } ) p add #DELETE dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} }, :attribute_updates => { "delete" => { :value => {:n => "100"}, :action => "DELETE" } }, ) delete = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} } ) p delete
{"Item"=>{"id"=>{"N"=>"1"}, "add"=>{"N"=>"1"}, "put"=>{"N"=>"1"}, "delete"=>{"N"=>"1"}}, "ConsumedCapacityUnits"=>0.5} {"Item"=>{"id"=>{"N"=>"1"}, "add"=>{"N"=>"1"}, "put"=>{"N"=>"100"}, "delete"=>{"N"=>"1"}}, "ConsumedCapacityUnits"=>0.5} {"Item"=>{"id"=>{"N"=>"1"}, "add"=>{"N"=>"101"}, "put"=>{"N"=>"100"}, "delete"=>{"N"=>"1"}}, "ConsumedCapacityUnits"=>0.5} /Users/tetsuyam/.rvm/gems/ruby-1.9.3-p385/gems/aws-sdk-1.10.0/lib/aws/core/client.rb:360:in `return_or_raise': One or more parameter values were invalid: Action DELETE is not supported for the type N (AWS::DynamoDB::Errors::ValidationException) from /Users/tetsuyam/.rvm/gems/ruby-1.9.3-p385/gems/aws-sdk-1.10.0/lib/aws/core/client.rb:461:in `client_request' from (eval):3:in `update_item' from updateItem1-2.rb:66:in `<main>'
PUTのときは、1→100。ADDのときは、1→101となることが確認できます。
DELETEだとエラーがでます。
タイプがNのときのDELETEでは、アトリビュートの値を指定する必要がないようです。(むしろ指定したらダメ)
#DELETE dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "1"} }, :attribute_updates => { "delete" => { :value => {:n => "100"}, :action => "DELETE" } }, )
とすると
{"Item"=>{"add"=>{"N"=>"101"}, "id"=>{"N"=>"1"}, "put"=>{"N"=>"100"}}, "ConsumedCapacityUnits"=>0.5}
となり、うまくいきました。
次に、SET型の場合を試したいと思います。
require 'rubygems' require 'aws-sdk' require './init.rb' dynamoClient = AWS::DynamoDB::Client.new({ :dynamo_db_endpoint => 'dynamodb.ap-northeast-1.amazonaws.com', :access_key_id => ACCESS, :secret_access_key => SECRET}) init = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} } ) p init #PUT dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} }, :attribute_updates => { "put" => { :value => {:ns => ["100"]}, :action => "PUT" } }, ) put = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} } ) p put #ADD dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} }, :attribute_updates => { "add" => { :value => {:ns => ["100"]}, :action => "ADD" } }, ) add = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} } ) p add #DELETE dynamoClient.update_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} }, :attribute_updates => { "delete" => { :value => {:ns => ["1"]}, :action => "DELETE" } }, ) delete = dynamoClient.get_item( :table_name => TABLE, :key => { :hash_key_element => {:n => "2"} } ) p delete |ruby|< >|| {"Item"=>{"id"=>{"N"=>"2"}, "add"=>{"NS"=>["3", "100", "2", "1"]}, "put"=>{"N"=>"100"}, "delete"=>{"NS"=>["3", "2", "1"]}}, "ConsumedCapacityUnits"=>0.5} {"Item"=>{"id"=>{"N"=>"2"}, "add"=>{"NS"=>["3", "2", "1"]}, "put"=>{"NS"=>["100"]}, "delete"=>{"NS"=>["3", "2","1"]}}, "ConsumedCapacityUnits"=>0.5} {"Item"=>{"id"=>{"N"=>"2"}, "add"=>{"NS"=>["3", "100", "2", "1"]}, "put"=>{"NS"=>["100"]}, "delete"=>{"NS"=>["3", "2", "1!]}}, "ConsumedCapacityUnits"=>0.5} {"Item"=>{"id"=>{"N"=>"2"}, "add"=>{"NS"=>["3", "100", "2", "1"]}, "put"=>{"NS"=>["100"]}, "delete"=>{"NS"=>["3", "2"]}}, "ConsumedCapacityUnits"=>0.5}
PUTでは置き換え、ADDでは追加、DELETEでは削除されていることがわかります。
ADDで足し算できるのは、カウントするときとかに便利そうですね。