DynamoDB で存在しないデータに対して delete-item した際にエラーを発生させたい
概要
DynamoDB で delete-item した際、削除対象のデータが存在しなかったとしてもエラーは発生しない。AWS CLI がその挙動なので、恐らくどの言語でも同じだと思う。
% aws dynamodb delete-item \ --table-name sample-table \ --key '{"pk": {"S": "sample-id"}, "sk": {"N": "1"}}'
じゃあ逆にエラーを発生させたい場合はどうするの?って思って調べてみたので下記に書いていく。ちなみに言語は TypeScript で。
通常の挙動
↑で書いた AWS CLI 版 delete-item を TypeScript で書くとこんな感じ。削除対象のデータが存在しなくてもエラーは出ない。
import * as DynamoDB from 'aws-sdk/clients/dynamodb'; const DYNAMODB_API_VERSION = '2012-10-08'; const REGION = 'ap-northeast-1'; const TABLE_NAME = 'sample-table'; const dynamodbDocumentClient = new DynamoDB.DocumentClient({ apiVersion: DYNAMODB_API_VERSION, region: REGION, }); (async () => { const params: DynamoDB.DocumentClient.DeleteItemInput = { TableName: TABLE_NAME, Key: { pk: 'sample-id', sk: 1, }, }; await dynamodbDocumentClient.delete(params).promise(); })();
エラーを発生させる版
ConditionExpression で PK、SK に該当するデータが存在するか確認すれば OK。
import * as DynamoDB from 'aws-sdk/clients/dynamodb'; const DYNAMODB_API_VERSION = '2012-10-08'; const REGION = 'ap-northeast-1'; const TABLE_NAME = 'sample-table'; const dynamodbDocumentClient = new DynamoDB.DocumentClient({ apiVersion: DYNAMODB_API_VERSION, region: REGION, }); (async () => { const params: DynamoDB.DocumentClient.DeleteItemInput = { TableName: TABLE_NAME, Key: { pk: 'sample-id', sk: 1, }, ExpressionAttributeNames: { '#pk': 'pk', '#sk': 'sk', }, ConditionExpression: 'attribute_exists(#pk) and attribute_exists(#sk)', }; try { await dynamodbDocumentClient.delete(params).promise(); } catch (e) { if (e.code === 'ConditionalCheckFailedException') { console.log('削除する対象のデータが存在しなかったよ'); } else { console.log('それ以外のエラーだよ'); } } })();
おまけ
try / catch で得たエラーの型がデフォルトで any になる記憶だったのだが、unknown になっていた。
調べてみると下記の記事でこんな記述があった。
TypeScript 4.4 から導入予定の useUnknownInCatchVariables 設定を使えば型アノテーションなしで catch した値を unknown として扱うことができます TypeScript のエラーハンドリングを考える - Qiita
tsconfig.json の useUnknownInCatchVariables を false にすると、今までの挙動に戻った。へえ〜。