この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、Step FunctionsステートマシンからDynamoDBテーブル上の複数のアイテムをUpdateItemする方法を確認し、AWS CDKで実装してみました。
PutItemとUpdateItemの違い
本題に入る前に、まずDynamoDBのPutItemとUpdateItemの違いについて確認します。
PutItemとUpdateItemは、どちらもDynamoDBテーブル上のアイテムを1つ更新するAPI操作ですが、その更新時の違いは以下のようになります。
説明 | |
---|---|
PutItem | 入力で指定したアイテムで、既存のアイテムを置き換える。 |
UpdateItem | 入力で指定した属性情報で、既存のアイテムの属性情報を更新する。 |
例えばDynamoDBテーブルに下記の既存アイテムがあるとします。deviceId
がPartition Keyです。
//既存アイテム
{
"deviceId": "d001",
"deviceName": "デバイス001",
"temperature": 25
}
この時以下の入力を指定して、PutItemを行った場合とUpdateItemを行った場合だと、
//入力
{
"deviceId": "d001",
"temperature": 8
}
アイテムの更新結果はそれぞれ以下のようになります。PutItemは入力で指定されていない属性は削除されますが、UpdateItemは残されます。
//PutItemの結果
{
"deviceId": "d001",
"temperature": 8
}
//UpdateItemの結果
{
"deviceId": "d001",
"deviceName": "デバイス001",
"temperature": 8
}
またいずれのAPI操作も既定では指定のキーのアイテムが存在しない場合はアイテム新規作成が行われます。
BatchWriteItemではUpdateItemができない
一方で、BatchWriteItemはDynamoDBテーブル上のアイテムを複数更新する操作ですが、行える更新操作はPutItemまたはDeleteItemのみです。UpdateItemは行なえません。
ドキュメントにも代わりにUpdateItemを直接使用するように書いてあります。
BatchWriteItem cannot update items. To update items, use the UpdateItem action.
Step FunctionsステートマシンからDynamoDBテーブル上の複数のアイテムをUpdateItemしたい
以上を踏まえると、Step FunctionsステートマシンからDynamoDBテーブル上の複数のアイテムをUpdateItemしたい場合、以下の方法が考えられます。
- MapステートでUpdateItemを使用する
- TransactWriteItemsを使用する
TransactWriteItemsではPutItem、UpdateItemまたはDeleteItemの更新操作が可能で、25個までのアイテムであれば一度のAPI操作で更新が可能です。また状態遷移の回数も一度で済みます。そこで今回はTransactWriteItemsで複数アイテムのUpdateを行ってみます。
やってみた
CDKコード
AWS CDKで実装します。DynamoDBテーブルとステートマシンを下記の通り定義します。
lib/aws-cdk-app-stack.ts
import * as cdk from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as tasks from '@aws-cdk/aws-stepfunctions-tasks';
import * as dynamodb from '@aws-cdk/aws-dynamodb';
export class AwsCdkAppStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const deviceTable = new dynamodb.Table(this, 'deviceTable', {
tableName: 'deviceTable',
partitionKey: { name: 'deviceId', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
});
const updateDeviceData = new tasks.CallAwsService(
this,
'updateDeviceData',
{
service: 'dynamodb',
action: 'transactWriteItems',
parameters: {
'TransactItems.$': '$.TransactItems',
},
iamResources: [deviceTable.tableArn],
iamAction: 'dynamodb:*',
}
);
new sfn.StateMachine(this, 'updateDeviceDataStateMachine', {
stateMachineName: 'updateDeviceDataStateMachine',
definition: updateDeviceData,
});
}
}
cdk deploy
でデプロイします。
動作
準備としてDynamoDBテーブルに以下のようにデータを作成しておきます。
以下のJsonを入力としてステートマシンを実行してみます。
{
"TransactItems": [
{
"Update": {
"TableName": "deviceTable",
"Key": { "deviceId": { "S": "d001" } },
"ExpressionAttributeValues": {
":temperature": { "N": "10" }
},
"ExpressionAttributeNames": {
"#temperature": "temperature"
},
"UpdateExpression": "SET #temperature = :temperature"
}
},
{
"Update": {
"TableName": "deviceTable",
"Key": { "deviceId": { "S": "d003" } },
"ExpressionAttributeValues": {
":temperature": { "N": "15" },
":deviceName": { "S": "デバイス003" }
},
"ExpressionAttributeNames": {
"#deviceName": "deviceName",
"#temperature": "temperature"
},
"UpdateExpression": "SET #deviceName = :deviceName, #temperature = :temperature"
}
}
]
}
ステートマシンの実行が成功しました。
テーブル上のデータが指定通りに更新されています。
参考
- DynamoDBのputItemとupdateItemの違い | ハックノート
- UpdateItem - Amazon DynamoDB
- PutItem - Amazon DynamoDB
- TransactWriteItems - Amazon DynamoDB
以上