SET and REMOVE in an UpdateExpression DynamoDB
DynamoDB の put-item にて、一部の属性の値のみを更新しつつ、とある属性を削除したかったため、動作を確認しました。
An update expression consists of one or more clauses. Each clause begins with a SET, REMOVE, ADD, or DELETE keyword. You can include any of these clauses in an update expression, in any order. However, each action keyword can appear only once.
ドキュメントにもある通り、put-item では、SET, REMOVE, ADD, DELETE のアクションを指定でき、それらを複数指定できます。これらのアクションは、put-item内で1度のみしか 使えないようです。
事前準備
テーブル TableName: Members, Key: id を作成します。
aws dynamodb create-table \
--table-name Members \
--attribute-definitions \
AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
データを2件投入します。
id: "1001", name: "takada", group_id: "100", location: "Tokyo"id: "1002", name: "ishikawa", group_id: "200", location: "Hokkaido"
aws dynamodb put-item \
--table-name Members \
--item \
"{\"id\": {\"S\": \"1001\"}, \"name\": {\"S\": \"takada\"}, \"group_id\": {\"S\": \"100\"}, \"location\": {\"S\": \"Tokyo\"}}"
aws dynamodb put-item \
--table-name Members \
--item \
"{\"id\": {\"S\": \"1002\"}, \"name\": {\"S\": \"ishikawa\"}, \"group_id\": {\"S\": \"200\"}, \"location\": {\"S\": \"Hokkaido\"}}"
SET のみ
まずは SET のみを使い、一部の属性のみ更新できるかを確認します。
id:1001 の location を、Tokyo から Chiba に変更します。location は、DynamoDB の予約語なので、--expression-attribute-namesで#locationを定義します。また、--return-values ALL_NEWで更新後の結果を返すように指定します。
結果を見ると、location 以外の値は変更されていないことを確認できます。
aws dynamodb update-item \
--table-name Members \
--key "{ \"id\": { \"S\":\"1001\" } }" \
--expression-attribute-names "{ \"#location\": \"location\" }" \
--update-expression "SET #location = :location_value" \
--expression-attribute-values \
" { \":location_value\": { \"S\": \"Chiba\" } }" \
--return-values ALL_NEW
{
"Attributes": {
"location": {
"S": "Chiba"
},
"id": {
"S": "1001"
},
"name": {
"S": "takada"
},
"group_id": {
"S": "100"
}
}
}
SET と REMOVE
locationを変更しつつ、group_idを削除する put-item のオペレーションを実行してみます。ちなみに、group_idが削除されている状態のときに実行しても問題なく成功します。
update-expression はこのように指定します: --update-expression "SET #location = :location_value REMOVE group_id"。REMOVEの前に,は不要です。
aws dynamodb update-item \
--table-name Members \
--key "{ \"id\": { \"S\":\"1001\" } }" \
--expression-attribute-names "{ \"#location\": \"location\" }" \
--update-expression "SET #location = :location_value REMOVE group_id" \
--expression-attribute-values \
" { \":location_value\": { \"S\": \"Kyoto\" } }" \
--return-values ALL_NEW
{
"Attributes": {
"id": {
"S": "1001"
},
"name": {
"S": "takada"
},
"location": {
"S": "Kyoto"
}
}
}
お試し
ここでお試しとして、同じ属性を SET と REMOVE で指定してみます。このように: --update-expression "SET #location = :location_value REMOVE #location"。実際に使うことはないと思われます。
結果は、以下のようにエラーが発生します。各アクションで同じ属性(document paths)は指定できないということですね。
aws dynamodb update-item \
--table-name Members \
--key "{ \"id\": { \"S\":\"1001\" } }" \
--expression-attribute-names "{ \"#location\": \"location\" }" \
--update-expression "SET #location = :location_value REMOVE #location" \
--expression-attribute-values \
" { \":location_value\": { \"S\": \"Kagawa\" } }" \
--return-values ALL_NEW
An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: Two document paths overlap with each other; must remove or rewrite one of these paths; path one: [location], path two: [location]
さらにお試しとして、SET -> REMOVE -> SET を指定してみます。このように: --update-expression "SET #location = :location_value REMOVE group_id SET #name = :name_value"。ちなみにnameも DynamoDB の予約語です。こちらも実際に使うことはないと思われます。
SET が複数指定されているので、ドキュメントにも記載されているようにエラーが発生します。
aws dynamodb update-item \
--table-name Members \
--key "{ \"id\": { \"S\":\"1001\" } }" \
--expression-attribute-names "{ \"#location\": \"location\", \"#name\": \"name\" }" \
--update-expression "SET #location = :location_value REMOVE group_id SET #name = :name_value" \
--expression-attribute-values \
" { \":location_value\": { \"S\": \"Kagawa\" }, \":name_value\": { \"S\": \"Doraemon\" } }" \
--return-values ALL_NEW
An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: The "SET" section can only be used once in an update expression;