DynamoDBの部分更新の方法がややこしかったことと、出来ることと出来ないことが分かったのでメモに残します。
※RubySDKの話です。
要件
- 既にitemが存在していなかったらitemを作成した上でデータを更新してほしい
- document要素内の配列の中の、指定したfood要素と同じ位にいるvalue要素を更新したい
- インクリメントにvalue要素を更新
itemの中身サンプル
{
"user": "doraemon",
"date": "2016-03-02",
"document": [
{
"food": "dorayaki",
"value": 10
},
{
"food": "apple",
"value": 4
}
]
}
update_item関数
パラメータ
- expression_attribute_names : 式に、予約語を利用したいときに定義するためのパラメータ
- update_expression : jsonデータを細かく編集するために定義する
- return_values : アップデートされた要素を返してくれるパラメータ
- return_consumed_capacity : スループットの定義を返してくれる?
- return_item_collection_metrics : itemのサイズを返してくれる?
- condition_expression : アップデートする上での条件を指定することができる
- expression_attribute_names : 要素名を変更するための代用トークン?
- expression_attribute_values : 要素の値を変更できる
- attribute_updates : 下位互換用のパラメータ。これを使うならupdate_expressionを使用することが推奨されている
- expected : 下位互換用のパラメータ。これを使うならcondition_expressionを使用することが推奨されている
- conditional_operator : 下位互換用のパラメータ。これを使うならcondition_expressionを使用することが推奨されている
必要なパラメータは以下?
- expression_attribute_names
- update_expression
update_expressionの使い方を見てみる
ADD
属性が存在しないなら、指定された値を追加する。値が存在するならば、ADDの行動は属性のデータ型に依存する。
もし既存の属性が数であり、値が数でもあるならば、値は既存の属性に数学的に追加される。もし値がネガティブな数であるならば、それは既存の属性から取り去られる。もしアップデートの前で存在しないアイテムのための数値をインクリメントするか、またはデクリメントするために、あなたがADDを使用するならば、DynamoDBは初期の値として0を使う。
より詳しい説明はこちらに載っている。
色々試してみてわかった知見
- update_expressionで'SET'で定義した値は、使わないとエラーになる
- 予約語は要確認!(item内で利用しているvalueは予約語となっているのでvalue要素内を使う場合はexpression_attribute_namesパラメータが必要)
- update_expressionは複数指定できそう
- SETでも数値属性を増減することができる
- ネストして要素を追加することはできなかった・・(2階層一気に追加する方法がわからない)
- update_expressionを二つ記述すると、最後に書いたパラメータのみが適用される(他は無視される)