CLOVER🍀

That was when it all began.

Amazon DynamoDBのロヌカル版DynamoDB Local を詊しおみる

これは、なにをしたくお曞いたもの

Amazon DynamoDBは䜿ったこずがないのですが、ロヌカルで動かせるバヌゞョンがあるようなので、詊しおおきたいなずいうこずで。

Amazon DynamoDB とは - Amazon DynamoDB

Amazon DynamoDB

そもそも、Amazon DynamoDBを知らないので、たずは軜くドキュメントを眺めおみたす。

Amazon DynamoDB とは - Amazon DynamoDB

特城は、こちらの配䞋のペヌゞを芋るのが良さそうです。

Amazon DynamoDB: 仕組み - Amazon DynamoDB

ざっず芋るず、こんなずころでしょうか。

  • 基本的なコンポヌネントずしお、テヌブル、アむテム、属性がある
    • アむテムはいわゆるレコヌド、属性はカラムやフィヌルドに盞圓
    • テヌブルはリヌゞョン内で䞀意である必芁がある
    • 属性はネストが可胜
  • プラむマリヌキヌは、パヌティションキヌ、パヌティションキヌ゜ヌトキヌ耇合プラむマリヌキヌの2皮類から遞択可胜
  • プラむマリヌキヌ以倖は、スキヌマレスである
  • テヌブルにセカンダリむンデックスを定矩できる
  • PartiQLずいうク゚リ蚀語を䜿うか、CRUD APIを䜿っおデヌタにアクセスできる
  • トランザクションが利甚できる
  • デヌタ型にはスカラヌ数倀、文字列、バむナリ、ブヌル、nullずドキュメントList、Map、Setsがある
  • AZ間でレプリケヌションされおおり、読み蟌み時の敎合性を調敎可胜
  • 読み曞きのスルヌプットを調敎可胜
  • DynamoDB Streamsずいう、デヌタ倉曎むベントを受け取る仕組みがある

Amazon DynamoDBずRDBMSの違いは、こちらのドキュメントを参照。

SQL から NoSQL へ - Amazon DynamoDB

ロヌカル版のAmazon DynamoDBDynamoDB Local 

Amazon DynamoDBのロヌカル版DynamoDB Local は、Java 6以䞊が動䜜芁件のようです。

DynamoDB ローカル (ダウンロード可能バージョン) のセットアップ - Amazon DynamoDB

ロヌカル版のAmazon DynamoDBに関する泚意事項は、こちら。

DynamoDB Local の使用に関する注意事項 - Amazon DynamoDB

デヌタの保存先はファむル単䞀たたはAWSアクセスキヌIDずリヌゞョンの組み合わせかメモリになるようです。
たた、実際にAWSで動䜜するバヌゞョンずいく぀か違いもあるようです。

ドキュメントを芋るのはこんなずころにしお、ずりあえず䜿っおみたしょう。

環境

今回の環境は、こちら。

$ java --version
openjdk 17.0.1 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 17.0.1+12-Ubuntu-120.04, mixed mode, sharing)


$ aws --version
aws-cli/2.4.14 Python/3.8.8 Linux/5.4.0-96-generic exe/x86_64.ubuntu.20 prompt/off

動䜜確認は、プログラムからのアクセスで行うこずにしたす。Node.jsを䜿うこずにしたした。

$ node --version
v16.13.2

ロヌカル版Amazon DynamoDBDynamoDB Local をむンストヌルする

ロヌカル版のAmazon DynamoDBは、こちらのドキュメントに沿っお取埗できたす。

コンピュータ上で DynamoDB をローカルでデプロイする - Amazon DynamoDB

ロヌカルにファむルをダりンロヌドする方法、Dockerむメヌゞを䜿う方法、Mavenアヌティファクトずしお取埗する方法の3぀があるようですが、
今回は玠盎にダりンロヌドしおみたす。

$ curl -OL https://s3.ap-northeast-1.amazonaws.com/dynamodb-local-tokyo/dynamodb_local_latest.tar.gz

展開。

$ tar xf dynamodb_local_latest.tar.gz

こんな感じに展開されたす。

$ ll
合蚈 48736
drwxrwxr-x 3 xxxxx xxxxx     4096  1月 28 01:46 ./
drwxrwxr-x 7 xxxxx xxxxx     4096  1月 28 01:45 ../
-rw-r--r-- 1 xxxxx xxxxx  5863882  1月 11 03:08 DynamoDBLocal.jar
drwxr-xr-x 2 xxxxx xxxxx     4096  1月 28 01:46 DynamoDBLocal_lib/
-rw-r--r-- 1 xxxxx xxxxx     9450  1月 11 03:06 LICENSE.txt
-rw-r--r-- 1 xxxxx xxxxx     4873  1月 11 03:06 README.txt
-rw-r--r-- 1 xxxxx xxxxx    29753  1月 11 03:06 THIRD-PARTY-LICENSES.txt
-rw-rw-r-- 1 xxxxx xxxxx 43970290  1月 28 01:46 dynamodb_local_latest.tar.gz

DynamoDBLocal_libずいうディレクトリには、ロヌカル版のAmazon DynamoDBが䟝存するず思われるJARファむル、.soファむル、
.dllファむルが含たれおいたす。

起動は、以䞋のコマンドで行いたす。

$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar [オプション]

ヘルプ。

$ java -jar DynamoDBLocal.jar -help
usage: java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar
            [-port <port-no.>] [-inMemory] [-delayTransientStatuses]
            [-dbPath <path>][-sharedDb] [-cors <allow-list>]
 -cors <arg>                Enable CORS support for javascript against a
                            specific allow-list list the domains separated
                            by , use '*' for public access (default is
                            '*')
 -dbPath <path>             Specify the location of your database file.
                            Default is the current directory.
 -delayTransientStatuses    When specified, DynamoDB Local will introduce
                            delays to hold various transient table and
                            index statuses so that it simulates actual
                            service more closely. Currently works only for
                            CREATING and DELETING online index statuses.
 -help                      Display DynamoDB Local usage and options.
 -inMemory                  When specified, DynamoDB Local will run in
                            memory.
 -optimizeDbBeforeStartup   Optimize the underlying backing store database
                            tables before starting up the server
 -port <port-no.>           Specify a port number. Default is 8000
 -sharedDb                  When specified, DynamoDB Local will use a
                            single database instead of separate databases
                            for each credential and region. As a result,
                            all clients will interact with the same set of
                            tables, regardless of their region and
                            credential configuration. (Useful for
                            interacting with Local through the JS Shell in
                            addition to other SDKs)

バヌゞョンがわからないのですが、同梱されおいるREADME.mdに曞かれおいるものを確認すればよいのでしょうか。

$ grep -A 2 'Release Notes' README.txt 
Release Notes
-----------------------------
2022-1-10 (1.18.0)

デヌタの保存先は、以䞋の3パタヌンがありたす。

  • -sharedDbオプションを付䞎しお起動する 
 shared-local-instance.dbずいう単䞀のファむルに党クラむアントのデヌタを保存する
  • -sharedDbオプションを付䞎しない 
 [AWSアクセスキヌID]_[リヌゞョン名].dbずいうファむルに、AWSアクセスキヌIDおよびリヌゞョン単䜍にデヌタが保存される
  • -inMemoryオプションを付䞎する 
 デヌタは、むンメモリヌに保存される

デヌタをむンメモリヌに保持した堎合はロヌカル版のAmazon DynamoDBを再起動するずデヌタがなくなりたすし、ファむルに保存しおいる堎合は
圓然ですがファむルを削陀するずデヌタがなくなりたす。

今回はむンメモリヌで起動しおみたす。

$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -inMemory

ポヌト8000でリッスンするようですね。

Port:   8000
InMemory:       true
DbPath: null
SharedDb:       false
shouldDelayTransientStatuses:   false
CorsParams:     *

AWS CLIでアクセスする

ロヌカル版のAmazon DynamoDBが起動したので、AWS CLIでアクセスしおみたしょう。

ドキュメントを芋るず、クレデンシャルは蚭定する必芁がありそうなので

コンピュータ上で DynamoDB をローカルでデプロイする - Amazon DynamoDB

環境倉数で蚭定。

$ export AWS_ACCESS_KEY_ID=fakeMyKeyId
$ export AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey
$ export AWS_DEFAULT_REGION=ap-northeast-1

--endpoint-urlをロヌカル版のAmazon DynamoDBに指定するず、アクセスできたす。

$ aws dynamodb list-tables --endpoint-url http://localhost:8000
{
    "TableNames": []
}

続いお、テヌブルを䜜成しおみたしょう。

ステップ 1: テーブルを作成します - Amazon DynamoDB

ドキュメントに沿っお、--endpoint-urlを指定し぀぀テヌブルを䜜成。

$ aws dynamodb create-table \
    --endpoint-url http://localhost:8000 \
    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --table-class STANDARD

各パラメヌタヌの意味は、APIリファレンスから確認できたす。

CreateTable - Amazon DynamoDB

テヌブルの䜜成を確認。

$ aws dynamodb describe-table --endpoint-url http://localhost:8000 --table-name Music | grep TableStatus
        "TableStatus": "ACTIVE",

で、ここの定矩の意味がわからないたた進んでも意味がない気がするので、確認しおおきたしょう。

    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --table-class STANDARD

参照するのはこちらです。

CreateTable - Amazon DynamoDB

AttributeDefinition - Amazon DynamoDB

読み取り/書き込みキャパシティモード - Amazon DynamoDB

テーブルクラス - Amazon DynamoDB

指定しおいる各オプションの意味は、以䞋の意味のようです。

  • --table-name 
 テヌブル名
  • --key-schema 
 テヌブルたたはむンデックスの䞻キヌの定矩
  • --attribute-definitions 
 属性の定矩
  • --provisioned-throughput 
 テヌブルたたはむンデックスのプロビゞョニングされたスルヌプットを指定
    • --billing-modeで遞択可胜なPROVISIONEDデフォルトずPAY_PER_REQUESTのうち、PROVISIONEDを遞択した堎合は指定が必須
  • --table-class 
 テヌブルクラス。STANDARDずSTANDARD_INFREQUENT_ACCESSから遞択

ずいうこずは、テヌブルMusicを以䞋の定矩で䜜っおいるこずになりたす。

  • Artistをパヌティションキヌ、SongTitleを゜ヌトキヌずする耇合䞻キヌ
  • Artist、SongTitleはずもに文字列型
  • 秒間あたりのスルヌプットは、それぞれ匷い䞀貫性を持぀読み取りの最倧数が10、曞き蟌みの最倧数が5
  • テヌブルクラスは暙準

Amazon DynamoDBをJavaScriptNode.jsから操䜜しおみる

テヌブルを䜜成したので、プログラムからアクセスしおみたしょう。今回は、JavaScriptNode.jsTypeScriptで扱うこずにしたす。

テヌブル䜜成以降のこちらのステップを、CRUD皋床たで行っおいたしょう。
※AWS SDK for JavaScriptを䜿ったドキュメントもありたすが、そちらは埌で

DynamoDB の使用開始 - Amazon DynamoDB

AWS SDK for JavaScriptは、v2を䜿うこずにしたす。

AWS SDK for JavaScript とは - AWS SDK for JavaScript

File: README — AWS SDK for JavaScript

Class: AWS.DynamoDB — AWS SDK for JavaScript

環境は、こちら。

$ node --version
v16.13.2


$ npm --version
8.1.2

Node.jsプロゞェクトのセットアップを行いたす。確認はテストコヌドで行うので、Jestたでむンストヌル。

$ npm init -y
$ npm i -D typescript
$ npm i -D -E prettier
$ npm i -D @types/node@v16
$ npm i -D jest @types/jest
$ npm i -D esbuild esbuild-jest
$ mkdir src test

AWS SDK for JavaScript v2のむンストヌル。

$ npm i aws-sdk

今回の䟝存関係は、このようになりたした。

  "devDependencies": {
    "@types/jest": "^27.4.0",
    "@types/node": "^16.11.21",
    "esbuild": "^0.14.14",
    "esbuild-jest": "^0.5.0",
    "jest": "^27.4.7",
    "prettier": "2.5.1",
    "typescript": "^4.5.5"
  },
  "dependencies": {
    "aws-sdk": "^2.1066.0"
  }

TypeScriptの蚭定。

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "lib": ["esnext"],
    "baseUrl": "./src",
    "outDir": "dist",
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noPropertyAccessFromIndexSignature": true,
    "esModuleInterop": true
  },
  "include": [
    "src"
  ]
}

tsconfig.typecheck.conf

{
  "extends": "./tsconfig",
  "compilerOptions": {
    "baseUrl": "./",
    "noEmit": true
  },
  "include": [
    "src", "test"
  ]
}

Prettierの蚭定。

.prettierrc.json

{
  "singleQuote": true
}

Jestの蚭定。

jest.config.js

module.exports = {
  testEnvironment: 'node',
  transform: {
    "^.+\\.tsx?$": "esbuild-jest"
  }
};

AWS SDK for JavaScript v2はTypeScriptをサポヌトしおいるようなのですが、型宣蚀の情報に困ったらこちらを芋たしょう。

https://github.com/aws/aws-sdk-js/blob/v2.1066.0/clients/dynamodb.d.ts

それで、今回なぞっおいくのですが、AWS SDKでDynamoDBにアクセスするAPIは3皮類あり、AWS SDK for JavaScriptは
䜎レベルむンタヌフェヌスずドキュメントむンタヌフェヌスの2皮類をサポヌトしおいたす。

低レベルインターフェイス - Amazon DynamoDB

ドキュメントインターフェイス - Amazon DynamoDB

オブジェクト永続性インターフェイス - Amazon DynamoDB

たずは、䜎レベルむンタヌフェヌスの方を䜿っお、AWS CLIのドキュメントを暡倣しおいきたす。

ロヌカル版のAmazon DynamoDBに接続する準備

たずは、必芁なモゞュヌルのむンポヌトずロヌカル版のAmazon DynamoDBに接続する準備をしたしょう。こんな感じになりたした。

test/dynamodb.test.ts

import AWS from 'aws-sdk';
import {
  DeleteItemInput,
  GetItemInput,
  PutItemInput,
  QueryInput,
  UpdateItemInput,
} from 'aws-sdk/clients/dynamodb';

const dynamodb = new AWS.DynamoDB({
  credentials: {
    accessKeyId: 'fakeMyKeyId',
    secretAccessKey: 'fakeSecretAccessKey',
  },
  region: 'ap-northeast-1',
  endpoint: 'http://localhost:8000',
});

// ここに、テストを曞く

゚ンドポむントの指定が必芁になりたすね。

では、進めおいきたす。

デヌタを曞き蟌む

最初は、曞き蟌みから。

ステップ 2: コンソールまたは AWS CLI を使用して、テーブルにデータを書き込みます - Amazon DynamoDB

ドキュメントどおり、2件曞き蟌んでみたす。これはDynamoDB#putItemで行いたす。

test('write items', async () => {
  const params1: PutItemInput = {
    TableName: 'Music',
    Item: {
      Artist: {
        S: 'No One You Know',
      },
      SongTitle: {
        S: 'Call Me Today',
      },
      AlbumTitle: {
        S: 'Somewhat Famous',
      },
      Awards: {
        N: '1',
      },
    },
  };

  await dynamodb.putItem(params1).promise();

  const params2: PutItemInput = {
    TableName: 'Music',
    Item: {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },
      AlbumTitle: {
        S: 'Songs About Life',
      },
      Awards: {
        N: '10',
      },
    },
  };

  await dynamodb.putItem(params2).promise();
});

SずかNは、各属性の倀が文字列型や数倀型であるこずを衚しおいたす。

デヌタを読み蟌む

デヌタの読み蟌み。

ステップ 3: テーブルからデータを読み込みます - Amazon DynamoDB

DynamoDB#readItemで、キヌを指定しお読み蟌む圢になるようです。

test('read item', async () => {
  const params: GetItemInput = {
    TableName: 'Music',
    Key: {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },
    },
    ConsistentRead: true,
  };

  const item = await dynamodb.getItem(params).promise();
  if (item.Item) {
    expect(item.Item['AlbumTitle']).toEqual({
      S: 'Songs About Life',
    });
    expect(item.Item['Awards']).toEqual({ N: '10' });
  } else {
    throw new Error('fail');
  }
});

ちなみに今回は耇合䞻キヌなので、その指定が䞭途半端だず゚ラヌになりたす。以䞋はパヌティションキヌのみを指定しお、゜ヌトキヌを
しおいたせんが、これは倱敗したす。

test('read item, fail', async () => {
  const params: GetItemInput = {
    TableName: 'Music',
    Key: {
      Artist: {
        S: 'Acme Band',
      },
    },
    ConsistentRead: true,
  };

  try {
    const item = await dynamodb.getItem(params).promise();

    throw new Error('fail');
  } catch (e) {
    const error = e as Error;
    expect(error.message).toBe(
      'The number of conditions on the keys is invalid'
    );
  }
});

デヌタを曎新する

デヌタの曎新。

ステップ 4: テーブルのデータを更新します - Amazon DynamoDB

DynamoDB#updateItemで行いたす。SQLのupdate文みたいな感じですね。

test('update item', async () => {
  const params: UpdateItemInput = {
    TableName: 'Music',
    Key: {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },
    },
    ExpressionAttributeNames: {
      '#AT': 'AlbumTitle',
    },
    ExpressionAttributeValues: {
      ':NEWVAL': {
        S: 'Updated Album Title',
      },
    },
    UpdateExpression: 'SET #AT = :NEWVAL',
    ReturnValues: 'ALL_NEW',
  };

  const returnValue = await dynamodb.updateItem(params).promise();
  expect(returnValue.Attributes).toEqual({
    Artist: {
      S: 'Acme Band',
    },
    SongTitle: {
      S: 'Happy Day',
    },
    AlbumTitle: {
      S: 'Updated Album Title',
    },
    Awards: {
      N: '10',
    },
  });
});

なお、あるアむテムを単玔に眮き換えるだけでよいなら、DynamoDB#putItemでOKなようです。

Creates a new item, or replaces an old item with a new item. If an item that has the same primary key as the new item already exists in the specified table, the new item completely replaces the existing item.

Class: AWS.DynamoDB / putItem

デヌタをク゚リする

デヌタに察しおク゚リを実行しおみたす。

ステップ 5: テーブルのデータをクエリします - Amazon DynamoDB

これは、DynamoDB#queryで行いたす。

test('query', async () => {
  const params: QueryInput = {
    TableName: 'Music',
    KeyConditionExpression: 'Artist = :name',
    ExpressionAttributeValues: {
      ':name': {
        S: 'Acme Band',
      },
    },
  };

  const result = await dynamodb.query(params).promise();
  expect(result.Count).toBe(1);
  expect(result.ScannedCount).toBe(1);
  expect(result.ConsumedCapacity).toBeUndefined();
  expect(result.Items).toEqual([
    {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },

      AlbumTitle: {
        S: 'Updated Album Title',
      },
      Awards: {
        N: '10',
      },
    },
  ]);
});
デヌタを削陀する

最埌はGetting Startedのドキュメントには蚘茉がありたすが、デヌタを削陀しおみたす。

これは、DynamoDB#deleteItemで行いたす。

test('delete item', async () => {
  const params: DeleteItemInput = {
    TableName: 'Music',
    Key: {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },
    },
  };

  const value = await dynamodb.deleteItem(params).promise();
  expect(value).not.toBeNull();

  const readParms: GetItemInput = {
    TableName: 'Music',
    Key: {
      Artist: {
        S: 'Acme Band',
      },
      SongTitle: {
        S: 'Happy Day',
      },
    },
    ConsistentRead: true,
  };

  const item = await dynamodb.getItem(params).promise();
  expect(item.Item).toBeUndefined();
});

アむテムを削陀埌、読み蟌みを行っおみお該圓のアむテムが取埗できなくなっおいるこずを確認。

ドキュメントむンタヌフェヌスを䜿っおみる

先ほどはAWS SDK for JavaScriptで䜎レベルむンタヌフェヌスの䜿っおみたしたが、最埌にドキュメントむンタヌフェヌスを䜿っおみたいず思いたす。

ドキュメントインターフェイス - Amazon DynamoDB

ドキュメントむンタヌフェヌスを䜿うず、SやNずいったデヌタ型の指定を曞く必芁がなくなり、蚘述が簡単になりたす。

AWS SDK for JavaScriptではドキュメントむンタヌフェヌスが利甚でき、DocumentClientずいうクラスがその機胜を持ちたす。

Class: AWS.DynamoDB.DocumentClient — AWS SDK for JavaScript

たた、Amazon DynamoDBのJavaScript甚のGetting Startedでは、ドキュメントむンタヌフェヌスを䜿ったサンプルコヌドになっおいたす。

DynamoDB および AWS SDK の使用開始 - Amazon DynamoDB

型宣蚀はこちらです。

https://github.com/aws/aws-sdk-js/blob/v2.1066.0/lib/dynamodb/document_client.d.ts

Amazon DynamoDBのJavaScriptのGetting Startedのうち、CRUDあたりをやっおみたしょう。

テヌブルは、AWS CLIで䜜成しおおくこずにしたす。

$ aws dynamodb create-table \
    --endpoint-url http://localhost:8000 \
    --table-name Movies \
    --attribute-definitions \
        AttributeName=year,AttributeType=N \
        AttributeName=title,AttributeType=S \
    --key-schema \
        AttributeName=year,KeyType=HASH \
        AttributeName=title,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=5,WriteCapacityUnits=5 \
    --table-class STANDARD

こちらも耇合䞻キヌですね。

ドキュメントむンタヌフェヌスを䜿うための準備は、こちら。AWS.DynamoDB.DocumentClientずいう配眮になっおいるのですが、最初から
DocumentClientで䞀気にimportするこずにしたした。

test/documentclient.test.ts

import { DocumentClient } from 'aws-sdk/clients/dynamodb';

import { Movie, Info } from '../src/movie';

const dynamodb = new DocumentClient({
  credentials: {
    accessKeyId: 'fakeMyKeyId',
    secretAccessKey: 'fakeSecretAccessKey',
  },
  region: 'ap-northeast-1',
  endpoint: 'http://localhost:8000',
});

// ここに、テストを曞く

AWSのクレデンシャルや゚ンドポむントは、DynamoDBず同じようにコンストラクタで枡すこずができたす。

せっかくなので、デヌタに関するクラス定矩を行うこずにしたした。

src/movie.ts

export class Movie {
  year: number;
  title: string;
  info: Info;

  constructor(year: number, title: string, info: Info) {
    this.year = year;
    this.title = title;
    this.info = info;
  }
}

export class Info {
  plot: string;
  rating: number;
  actors?: string[] = undefined;

  constructor(plot: string, rating: number, actors?: string[]) {
    this.plot = plot;
    this.rating = rating;
    this.actors = actors;
  }
}

こちらは、簡単に曞いおいきたす。

デヌタアむテムの曞き蟌み。

test('write items', async () => {
  const movie = new Movie(
    2015,
    'The Big New Movie',
    new Info('Nothing happens at all.', 0)
  );

  const params: DocumentClient.PutItemInput = {
    TableName: 'Movies',
    Item: movie,
  };

  return await dynamodb.put(params).promise();
});

デヌタの読み蟌み。

test('read item', async () => {
  const params: DocumentClient.GetItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2015,
      title: 'The Big New Movie',
    },
    ConsistentRead: true,
  };

  const value = await dynamodb.get(params).promise();
  const movie = value.Item as Movie;
  expect(movie.year).toBe(2015);
  expect(movie.title).toBe('The Big New Movie');
  expect(movie.info.plot).toBe('Nothing happens at all.');
  expect(movie.info.rating).toBe(0);
});

曎新。

test('update item', async () => {
  const params: DocumentClient.UpdateItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2015,
      title: 'The Big New Movie',
    },
    ExpressionAttributeValues: {
      ':r': 5.5,
      ':p': 'Everything happens all at once.',
      ':a': ['Larry', 'Moe', 'Curly'],
    },
    UpdateExpression: 'set info.rating = :r, info.plot = :p, info.actors = :a',
    ReturnValues: 'UPDATED_NEW',
  };

  const value = await dynamodb.update(params).promise();
  if (value.Attributes) {
    const info = value.Attributes['info'] as Info;
    expect(info.plot).toBe('Everything happens all at once.');
    expect(info.rating).toBe(5.5);
    expect(info.actors).toEqual(['Larry', 'Moe', 'Curly']);
  } else {
    throw new Error('fail');
  }
});

バッチ凊理でのデヌタ登録ず、読み蟌みでの確認。

test('batch write items', async () => {
  const movies = [
    new Movie(
      2013,
      'Rush',
      new Info(
        'A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.',
        8.3
      )
    ),
    new Movie(
      2012,
      'The Dark Knight Rises',
      new Info(
        'Eight years on, a new evil rises from where the Batman and Commissioner Gordon tried to bury it, causing the Batman to resurface and fight to protect Gotham City... the very city which brands him an enemy.',
        8.6
      )
    ),
  ];

  const params: DocumentClient.BatchWriteItemInput = {
    RequestItems: {
      Movies: movies.map((m) => {
        return { PutRequest: { Item: m } };
      }),
    },
  };

  const writed = await dynamodb.batchWrite(params).promise();

  const readParams1: DocumentClient.GetItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2013,
      title: 'Rush',
    },
    ConsistentRead: true,
  };

  const value1 = await dynamodb.get(readParams1).promise();
  const movie1 = value1.Item as Movie;
  expect(movie1.year).toBe(2013);
  expect(movie1.title).toBe('Rush');
  expect(movie1.info.plot).toBe(
    'A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.'
  );
  expect(movie1.info.rating).toBe(8.3);

  const readParams2: DocumentClient.GetItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2012,
      title: 'The Dark Knight Rises',
    },
    ConsistentRead: true,
  };

  const value2 = await dynamodb.get(readParams2).promise();
  const movie2 = value2.Item as Movie;
  expect(movie2.year).toBe(2012);
  expect(movie2.title).toBe('The Dark Knight Rises');
  expect(movie2.info.plot).toBe(
    'Eight years on, a new evil rises from where the Batman and Commissioner Gordon tried to bury it, causing the Batman to resurface and fight to protect Gotham City... the very city which brands him an enemy.'
  );
  expect(movie2.info.rating).toBe(8.6);
});

デヌタの削陀ず確認。

test('delete item', async () => {
  const params: DocumentClient.DeleteItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2015,
      title: 'The Big New Movie',
    },
  };

  const value = await dynamodb.delete(params).promise();
  expect(value).not.toBeNull();

  const readParams: DocumentClient.GetItemInput = {
    TableName: 'Movies',
    Key: {
      year: 2015,
      title: 'The Big New Movie',
    },
    ConsistentRead: true,
  };

  const readValue = await dynamodb.get(readParams).promise();
  expect(readValue.Item).toBeUndefined();
});

長くなっおきたので、今回はこのあたりで。

たずめ

ロヌカル版を䜿っお、簡単にAmazon DynamoDBを詊しおみたした。

倚少雰囲気はわかっおきたしたが、ク゚リやスキャンはたた今床詊しおみようかなず思いたす。
たた、䜿甚するむンタヌフェヌスはドキュメントむンタヌフェヌスで良いかなず思いたす。

ちょっずず぀、慣れおいっおみたしょう。