DocumentClient を使用して DynamoDB からデータを取得〜アトミックカウンター等〜

AWS.DynamoDB.DocumentClient を使用して DynamoDB からデータを取得する方法を紹介します。

今回は結果生合成、キャパシティーユニットの数を取得する方法、アトミックカウンターを紹介していきます。

 

動作環境は AWS Lambda Node.js 10.X で確認しています。

 

結果生合成を有効にする

次のテーブルから結果生合成を有効にしてデータを取得します。

テーブル名:Music

プライマリパーティションキー:Artist プライマリソートキー:SongTitle

データを取得

コード

var AWS = require('aws-sdk');
var documentClient = new AWS.DynamoDB.DocumentClient({
  apiVersion: '2012-08-10',
  region: "ap-northeast-1"
});

exports.handler = async(event) => {
  var params = {
    TableName: 'Music',
    ConsistentRead: true
  };

  var result;
  try {
    result = await documentClient.scan(params).promise();
  }
  catch (e) {
    result = e;
  }

  return {
    statusCode: 200,
    body: result,
  };
};

結果

{
  "Items": [
    {
      "Artist": "マドンナ",
      "ReleaseDate": "1984/11/12",
      "SongTitle": "ライクアヴァージン"
    },
    {
      "Artist": "アヴリルラヴィーン",
      "ReleaseDate": "2007/02/07",
      "SongTitle": "ガールフレンド"
    },
    {
      "Artist": "マイケルジャクソン",
      "ReleaseDate": "1982/12/01",
      "SongTitle": "スリラー"
    },
    {
      "Artist": "マイケルジャクソン",
      "ReleaseDate": "1983/02/03",
      "SongTitle": "ビートイット"
    }
  ],
  "Count": 4,
  "ScannedCount": 4
}

 

"ConsistentRead: true"を指定することによって結果生合成が有効になります。

 

結果生合成とは簡単に言うと、DynamoDBはRDB(Oracle, SQLServer, MySQL等)のようにトランザクションによって一貫性を保っているわけではないので、

DynamoDBがデータを返却している最中にデータが変わった場合、一貫性が保てなくなります。

例えば1行目は前のデータなのに2行目以降は最新のデータになることもあります。

 

それを防いでくれるのが結果生合成です。

 

消費されるキャパシティーユニットの数を取得

 

次のテーブルからデータを取得する際に消費されるキャパシティーユニットの数を取得します。

テーブル名:Music

データを取得

コード

var AWS = require('aws-sdk');
var documentClient = new AWS.DynamoDB.DocumentClient({
    apiVersion: '2012-08-10',
    region: "ap-northeast-1"
});

exports.handler = async(event) => {
  var params = {
    TableName: 'Music',
    ReturnConsumedCapacity: 'INDEXES'
  };

  var result;
  try {
    result = await documentClient.scan(params).promise();
  }
  catch (e) {
    result = e;
  }

  return {
    statusCode: 200,
    body: result,
  };
};

 

結果

{
  "Items": [
    {
      "Artist": "マドンナ",
      "ReleaseDate": "1984/11/12",
      "SongTitle": "ライクアヴァージン"
    },
    {
      "Artist": "アヴリルラヴィーン",
      "ReleaseDate": "2007/02/07",
      "SongTitle": "ガールフレンド"
    },
    {
      "Artist": "マイケルジャクソン",
      "ReleaseDate": "1982/12/01",
      "SongTitle": "スリラー"
    },
    {
      "Artist": "マイケルジャクソン",
      "ReleaseDate": "1983/02/03",
      "SongTitle": "ビートイット"
    }
  ],
  "Count": 4,
  "ScannedCount": 4,
  "ConsumedCapacity": {
    "TableName": "Music",
    "CapacityUnits": 0.5,
    "Table": {
      "CapacityUnits": 0.5
    }
  }
}

 

「ReturnConsumedCapacity: 'INDEXES'」を指定するとキャパシティーユニットが取得できます。

AWSの使用料金に関わってくる値なので、チューニング時なんかによく使うオプションだと思います。

 

アトミックカウンター

 

次のようなテーブルを作成してください。

テーブル

 

このテーブルを利用して一意な連番を取得する処理を書いていきます。

 

コード

var AWS = require('aws-sdk');
var documentClient = new AWS.DynamoDB.DocumentClient({
    apiVersion: '2012-08-10',
    region: "ap-northeast-1"
});
 
exports.handler = async(event) => {
  var params = {
    TableName: 'MIndex',
    Key: {
      Name: 'MusicId'
    },
    UpdateExpression: 'SET LastId = if_not_exists(LastId, :ZERO) + :Increment',
    ExpressionAttributeValues: {
      ':ZERO': 0,
      ':Increment': 1
    },
    ReturnValues: 'UPDATED_NEW'
  };
 
  var result;
  try {
    result = await documentClient.update(params).promise();
  }
  catch (e) {
    result = e;
  }
 
  return {
    statusCode: 200,
    body: result,
  };
};

 

結果

{ "Attributes": { "LastId": 1 } }

 

アトミックカウンターを使用すると一意なIDを取得する事ができます。

Oracleの"select seq1.nextval from dual"、

SQLServerの"IDENTITY"、

MySQLの"AUTO_INCREMENT"に近い物だと思ってください。

 

サーバーレスでできて、同時アクセスしても一意な値が取得できるので、

私的にはDynamoDBで一番使うテクニックだと思います。

 

"UpdateExpression: 'SET LastId = if_not_exists(LastId, :ZERO) + :Increment'"

ここで1づつインクリメントしています。

"if_not_exists"で初期値を"0"にしてからインクリメントしているので実質1始まりのIDになります。

 

"ReturnValues: 'UPDATED_NEW'"

ここでインクリメントした結果どうなったかを返すように指定しています。

 

 

 

アプリケーション開発バナー