6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DynamoDBの条件付き Putでハマったので整理しておく

Posted at

はじめに

会社でDynamoDBの条件付き書き込みを使う機会があったのですが、数時間ハマってしまったので今後のためにも整理したいと思います。

Condition Expressionsとは

  • DynamoDBではデータの追加・更新・削除を行いたい場合に、PutItem, UpdateItem, DeleteItemなどを利用する
  • これらの処理を行う際に条件を指定することができる
  • 条件に一致する場合は処理を実施し、一致しない場合は処理を行わない

Condition Putとは

  • PutItemは以下の処理を行う
    • DynamoDB内に同じキーが存在しない場合、データを新規追加する
    • DynamoDB内に同じキーが存在する場合、データを上書きする

具体例(データ上書きの場合)

以下のテーブルが存在すると仮定します。

Partition Key Sort Key Attribute
Id Price ProductCategory
123 650 Sporting Goods

上記のテーブルは以下を表しています。

  • Id (Partition Key): 123
  • Price (Sort Key): 650
  • ProductCategory (Attribute): Sporting Goods

上記のテーブルに対して、以下のようにPut処理を行うと、テーブル内のデータが上書きされてしまいます。

aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json \
item.json
{
    "Id": {
        "N": "123"
    },
    "Price": {
        "N": "650"
    },
    "ProductCategory": {
        "S": "Sporting Goods"
    }
}

なぜなら、キーであるIdとPriceが同じ値だからです。
上書きしたくない場合は、以下のようにcondition-expressionを追加します。

aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json \
    --condition-expression "attribute_not_exists(Id)"

ハマったこと: プライマリキーが同じであれば条件付き putが動作すると思った

以下のCondition Expressionをみれば分かりますが、attribute_not_exists(Id)とあるので、てっきりIdがテーブル内に存在していれば動作すると思っていました。

condition-expression "attribute_not_exists(Id)"

そこで以下を試しました。

テーブルの状態

Partition Key Sort Key Attribute
Id Price ProductCategory
123 650 Sporting Goods

コマンド

aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json \
    --condition-expression "attribute_not_exists(Id)"

item.jsonはIdはテーブルと同じで、Priceは違う値としました。

item.json
{
    "Id": {
        "N": "123"
    },
    "Price": {
        "N": "550"
    },
    "ProductCategory": {
        "S": "New Sporting Goods"
    }
}

結果

条件付きputが効かず、以下のようにデータが保存されました。

Partition Key Sort Key Attribute
Id Price ProductCategory
123 650 Sporting Goods
123 550 New Sporting Goods

理由

公式ドキュメントを読むと、以下の記載がありました。

The PutItem operation overwrites an item with the same key (if it exists).
If you want to avoid this, use a condition expression.
This allows the write to proceed only if the item in question does not already have the same key.

Ref:https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html

意味としては以下です。

  • PutItem は同じキーの項目が存在する場合に条件付きputが機能する
  • 同じキーの項目が存在しない場合はデータが書き込まれる

つまり、条件付き putを使用する場合はputしようとするデータのキーがDynamoDB内のキーと一致している必要があります。
上記の例ではキーはIdPriceなので、これらが一致していないといけません。

検証内容まとめ

他のパターンもいろいろ試した結果をまとめると以下になります。
上記のハマったケースは、以下のパターン3になります。
以下の通り、キーが同じ場合に条件付き Putが動作します。
それ以外の場合は条件付きPutは動作しません。

パターン PK:Id SK:Price ProductCategory condition-expression 結果:条件付きPut動作有無
1 同じ 同じ 異なる attribute_not_exists(Id) 動作する
2 同じ 同じ 異なる attribute_not_exists(Price) 動作する
3 同じ 異なる 異なる attribute_not_exists(Id) 動作しない
4 同じ 異なる 同じ attribute_not_exists(Id) 動作しない
5 同じ 異なる 同じ attribute_not_exists(ProductCategory) 動作しない

まとめ

DynamoDBの条件付きputでハマったので整理しました。
条件付きputを使用する際は投入するデータのキーとDynamoDB内のデータのキーが同じ場合にしか動作しないことを覚えておくと良さそうです。

参考

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?