[Amazon DynamoDB] 各種データ更新操作(putItem、updateItem)による変更データキャプチャのストリームデータの内容を確認してみた

2021.12.22

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、Amazon DynamoDBでの各種データ更新操作(putItem、updateItem)による変更データキャプチャのストリームデータの内容を確認してみました。

DynamoDBのストリームデータって更新時はどうなるんだっけ?

Amazon DynamoDBでは、各データ操作時の変更データをキャプチャする設定して、そのキャプチャデータをストリームとして別の機能に連携することができます。

ストリームから得られるデータは次のような構成になります。NewImageOldImageに新旧のデータが格納される形になります。

{
  "eventID":"2",
  "eventName":"MODIFY",
  "eventVersion":"1.0",
  "eventSource":"aws:dynamodb",
  "awsRegion":"us-east-1",
  "dynamodb":{
    "Keys":{
        "Id":{
          "N":"101"
        }
    },
    "NewImage":{
        "Message":{
          "S":"This item has changed"
        },
        "Id":{
          "N":"101"
        }
    },
    "OldImage":{
        "Message":{
          "S":"New item!"
        },
        "Id":{
          "N":"101"
        }
    },
    "SequenceNumber":"222",
    "SizeBytes":59,
    "StreamViewType":"NEW_AND_OLD_IMAGES"
  },
  "eventSourceARN":"stream-ARN"
}

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-ddb.html

最近このDynamoDBの変更データキャプチャを使用した実装を行うことがあったのですが、その際にキャプチャデータの構成はPutItemUpdateItemなどの操作によって違いがあるのか?というのが気になったので確認してみました。

確認してみた

次の構成を作成して、各種操作を行ってみます。

次のスクリプトを実行してPutItemUpdateItemのデータ更新操作を実行してみます。

行っている更新操作は次の5パターンです。

  • PutItem
    • 新規作成
    • プロパティ値変更
    • プロパティ削除
    • プロパティ追加
  • UpdateItem
    • 一部プロパティ値変更
import * as AWS from 'aws-sdk';

const dynamodb = new AWS.DynamoDB({ region: 'ap-northeast-1' });

it('データ更新操作', async () => {
  const deviceId = 'd001';

  //PutItem(新規作成)
  await dynamodb
    .putItem({
      Item: {
        deviceId: {
          S: deviceId,
        },
        deviceName: {
          S: 'デバイス001',
        },
        position: {
          S: 'A-25',
        },
      },
      TableName: 'devicesTable',
    })
    .promise();

  //PutItem(プロパティ値変更)
  await dynamodb
    .putItem({
      Item: {
        deviceId: {
          S: deviceId,
        },
        deviceName: {
          S: 'デバイス001',
        },
        position: {
          S: 'B-20',
        },
      },
      TableName: 'devicesTable',
    })
    .promise();

  //PutItem(プロパティ削除)
  await dynamodb
    .putItem({
      Item: {
        deviceId: {
          S: deviceId,
        },
        deviceName: {
          S: 'デバイス001',
        },
      },
      TableName: 'devicesTable',
    })
    .promise();

  //PutItem(プロパティ追加)
  await dynamodb
    .putItem({
      Item: {
        deviceId: {
          S: deviceId,
        },
        deviceName: {
          S: 'デバイス001',
        },
        position: {
          S: 'C-05',
        },
      },
      TableName: 'devicesTable',
    })
    .promise();

  //UpdateItem(一部プロパティ値変更)
  await dynamodb
    .updateItem({
      Key: {
        deviceId: {
          S: deviceId,
        },
      },
      ExpressionAttributeValues: {
        ':deviceName': {
          S: 'デバイス0000001',
        },
      },
      ExpressionAttributeNames: {
        '#deviceName': 'deviceName',
      },
      UpdateExpression: 'set #deviceName = :deviceName',
      TableName: 'devicesTable',
    })
    .promise();
});

操作を行ってから少しするとS3バケット内にオブジェクトが生成されました。

このオブジェクトに対してS3 Selectをすると次のような結果を得られました。

//PutItem(新規作成)
//  新規作成なのでNewImageでのみデータのすべてのプロパティが記録されている
{
  "awsRegion": "ap-northeast-1",
  "eventID": "e949e41e-d088-4ffb-855f-c7bff2fa79b6",
  "eventName": "INSERT",
  "userIdentity": null,
  "recordFormat": "application/json",
  "tableName": "devicesTable",
  "dynamodb": {
    "ApproximateCreationDateTime": 1640184077807,
    "Keys": {
      "deviceId": {
        "S": "d001"
      }
    },
    "NewImage": {
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      },
      "position": {
        "S": "A-25"
      }
    },
    "SizeBytes": 61
  },
  "eventSource": "aws:dynamodb"
}

//PutItem(プロパティ値変更)
//  OldImageで変更前、NewImageで変更後のデータのすべてのプロパティが記録されている
{
  "awsRegion": "ap-northeast-1",
  "eventID": "3e908ea4-6b4f-40b4-a098-1c8b0172fde8",
  "eventName": "MODIFY",
  "userIdentity": null,
  "recordFormat": "application/json",
  "tableName": "devicesTable",
  "dynamodb": {
    "ApproximateCreationDateTime": 1640184109255,
    "Keys": {
      "deviceId": {
        "S": "d001"
      }
    },
    "NewImage": {
      "position": {
        "S": "B-20"
      },
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "OldImage": {
      "position": {
        "S": "A-25"
      },
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "SizeBytes": 110
  },
  "eventSource": "aws:dynamodb"
}

//PutItem(プロパティ削除)
//  OldImageでのみ削除前のプロパティが記録されている
{
  "awsRegion": "ap-northeast-1",
  "eventID": "7c7c1f3d-93b0-45b7-9bb9-ec778822fb51",
  "eventName": "MODIFY",
  "userIdentity": null,
  "recordFormat": "application/json",
  "tableName": "devicesTable",
  "dynamodb": {
    "ApproximateCreationDateTime": 1640184109318,
    "Keys": {
      "deviceId": {
        "S": "d001"
      }
    },
    "NewImage": {
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "OldImage": {
      "position": {
        "S": "B-20"
      },
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "SizeBytes": 98
  },
  "eventSource": "aws:dynamodb"
}

//PutItem(プロパティ追加)
//  NewImageでのみ追加したプロパティが記録されている
{
  "awsRegion": "ap-northeast-1",
  "eventID": "36f03059-96eb-4a86-8717-25697c7d77ce",
  "eventName": "MODIFY",
  "userIdentity": null,
  "recordFormat": "application/json",
  "tableName": "devicesTable",
  "dynamodb": {
    "ApproximateCreationDateTime": 1640184109371,
    "Keys": {
      "deviceId": {
        "S": "d001"
      }
    },
    "NewImage": {
      "position": {
        "S": "C-05"
      },
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "OldImage": {
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "SizeBytes": 98
  },
  "eventSource": "aws:dynamodb"
}

//UpdateItem(一部プロパティ値変更)
//  update対象であるかに関わらず、すべてのプロパティの変更前後の値が記録されている
{
  "awsRegion": "ap-northeast-1",
  "eventID": "e475ba62-78fb-4e4d-9a9f-a8f3748013a3",
  "eventName": "MODIFY",
  "userIdentity": null,
  "recordFormat": "application/json",
  "tableName": "devicesTable",
  "dynamodb": {
    "ApproximateCreationDateTime": 1640184109433,
    "Keys": {
      "deviceId": {
        "S": "d001"
      }
    },
    "NewImage": {
      "position": {
        "S": "C-05"
      },
      "deviceName": {
        "S": "デバイス0000001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "OldImage": {
      "position": {
        "S": "C-05"
      },
      "deviceName": {
        "S": "デバイス001"
      },
      "deviceId": {
        "S": "d001"
      }
    },
    "SizeBytes": 114
  },
  "eventSource": "aws:dynamodb"
}

結論として、どのような変更操作であるかに関わらず、操作前後のデータのすべてのプロパティがNewImageとOldImageに記録されるということが確認できました!

参考

以上