mcpField
D
dynamodb-toolbox-patterns

dynamodb-toolbox-patterns

github.com/giuseppe-trisciuoglioデータ・データベース3653.5k 回インストール7 週間前に更新
リポジトリ

dynamodb-toolbox-patterns について

AWS SDK v3 DocumentClient と DynamoDB-Toolbox v2 を使う開発者向けの TypeScript パターンをまとめたスキルです。型安全なスキーマ、コマンド構築、シングルテーブルのアクセス設計を扱います。

主な機能

  1. 01型安全なスキーマモデリング
  2. 02`.build()` による CRUD コマンド
  3. 03クエリとスキャンのアクセスパス
  4. 04バッチ処理とトランザクションのパターン
  5. 05シングルテーブル設計の指針

活用シーン

  1. 01DynamoDB のエンティティとスキーマ定義
  2. 02型付き CRUD 操作の実装
  3. 03キーと GSI アクセスパスの設計
  4. 04バッチ書き込みとトランザクションの選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill dynamodb-toolbox-patterns

インストール後、Claude Code で/dynamodb-toolbox-patternsを入力して読み込まれたか確認します。

同梱ファイルreferences/api-dynamodb-toolbox-v2.md

詳細

DynamoDB-Toolbox v2 のパターン(TypeScript)

概要

このスキルでは、AWS SDK v3 DocumentClient で DynamoDB-Toolbox v2 を使用するための、実践的な TypeScript のパターンを紹介します。型安全なスキーマモデリング、.build() コマンドの使用、本番環境に対応したシングルテーブル設計に焦点を当てています。

使用する場面

  • 厳密な TypeScript の型推論を利用して DynamoDB のテーブルとエンティティを定義する場合
  • item、string、number、list、set、map、record を使ってスキーマをモデリングする場合
  • .build() を使用して GetItem、PutItem、UpdateItem、DeleteItem を実装する場合
  • プライマリキーと GSI を使ってクエリおよびスキャンのアクセスパスを構築する場合
  • バッチ処理およびトランザクション処理を扱う場合
  • 計算キーとエンティティパターンを使ってシングルテーブルシステムを設計する場合

手順

  1. アクセスパターンから始める:まず読み取り/書き込みクエリを特定し、その後でキーを設計します。
  2. テーブルとエンティティの境界を作る:シングルテーブル設計を使用する場合は、1 つのテーブルに複数のエンティティを作成します。
  3. 制約付きでスキーマを定義する:.key()、.required()、.default()、.transform()、.link() を適用します。
  4. すべての箇所で .build() コマンドを使用する:一貫性と型安全性を保つため、場当たり的なコマンドの構築は避けます。
  5. クエリ/インデックスのカバレッジを確保する:必要な各アクセスパターンについて、GSI/LSI のパスを検証します。
  6. バッチ処理/トランザクションを適切に使う:スループットにはバッチ処理、アトミック性にはトランザクションを使用します。
  7. アイテムを進化可能に保つ:スキーマの進化に備えて、オプションフィールド、デフォルト値、派生属性を使用します。

例

インストールとセットアップ
npm install dynamodb-toolbox @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
import { Table } from 'dynamodb-toolbox/table';
import { Entity } from 'dynamodb-toolbox/entity';
import { item, string, number, list, map } from 'dynamodb-toolbox/schema';

const client = new DynamoDBClient({ region: process.env.AWS_REGION ?? 'eu-west-1' });
const documentClient = DynamoDBDocumentClient.from(client);

export const AppTable = new Table({
  name: 'app-single-table',
  partitionKey: { name: 'PK', type: 'string' },
  sortKey: { name: 'SK', type: 'string' },
  indexes: {
    byType: { type: 'global', partitionKey: { name: 'GSI1PK', type: 'string' }, sortKey: { name: 'GSI1SK', type: 'string' } }
  },
  documentClient
});
修飾子と複雑な属性を含むエンティティスキーマ
const now = () => new Date().toISOString();

export const UserEntity = new Entity({
  name: 'User',
  table: AppTable,
  schema: item({
    tenantId: string().required('always'),
    userId: string().required('always'),
    email: string().required('always').transform(input => input.toLowerCase()),
    role: string().enum('admin', 'member').default('member'),
    loginCount: number().default(0),
    tags: list(string()).default([]),
    profile: map({
      displayName: string().optional(),
      timezone: string().default('UTC')
    }).default({ timezone: 'UTC' })
  }),
  computeKey: ({ tenantId, userId }) => ({
    PK: `TENANT#${tenantId}`,
    SK: `USER#${userId}`,
    GSI1PK: `TENANT#${tenantId}#TYPE#USER`,
    GSI1SK: `EMAIL#${userId}`
  })
});
.build() による CRUD コマンド
import { PutItemCommand } from 'dynamodb-toolbox/entity/actions/put';
import { GetItemCommand } from 'dynamodb-toolbox/entity/actions/get';
import { UpdateItemCommand, $add } from 'dynamodb-toolbox/entity/actions/update';
import { DeleteItemCommand } from 'dynamodb-toolbox/entity/actions/delete';

await UserEntity.build(PutItemCommand)
  .item({ tenantId: 't1', userId: 'u1', email: '[email protected]' })
  .send();

const { Item } = await UserEntity.build(GetItemCommand)
  .key({ tenantId: 't1', userId: 'u1' })
  .send();

await UserEntity.build(UpdateItemCommand)
  .item({ tenantId: 't1', userId: 'u1', loginCount: $add(1) })
  .send();

await UserEntity.build(DeleteItemCommand)
  .key({ tenantId: 't1', userId: 'u1' })
  .send();
クエリとスキャンのパターン
import { QueryCommand } from 'dynamodb-toolbox/table/actions/query';
import { ScanCommand } from 'dynamodb-toolbox/table/actions/scan';

const byTenant = await AppTable.build(QueryCommand)
  .query({
    partition: `TENANT#t1`,
    range: { beginsWith: 'USER#' }
  })
  .send();

const byTypeIndex = await AppTable.build(QueryCommand)
  .query({
    index: 'byType',
    partition: 'TENANT#t1#TYPE#USER'
  })
  .options({ limit: 25 })
  .send();

const scanned = await AppTable.build(ScanCommand)
  .options({ limit: 100 })
  .send();
バッチ処理とトランザクションのワークフロー
import { BatchWriteCommand } from 'dynamodb-toolbox/table/actions/batchWrite';
import { TransactWriteCommand } from 'dynamodb-toolbox/table/actions/transactWrite';

await AppTable.build(BatchWriteCommand)
  .requests(
    UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u2', email: '[email protected]' }),
    UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u3', email: '[email protected]' })
  )
  .send();

await AppTable.build(TransactWriteCommand)
  .requests(
    UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u4', email: '[email protected]' }),
    UserEntity.build(UpdateItemCommand).item({ tenantId: 't1', userId: 'u1', loginCount: $add(1) })
  )
  .send();

シングルテーブル設計の指針

  • 各ビジネス概念を、厳密なスキーマを持つエンティティとしてモデリングします。
  • PK/SK は予測可能で組み合わせ可能な形式にします(TENANT#、USER#、ORDER#)。
  • アクセスパスはメモリ内のフィルターではなく、GSI キーにエンコードします。
  • 監査/履歴データには、追記専用のタイムラインを優先します。
  • 必要に応じてスコープを限定したパーティションやシャーディングを使用し、ホットパーティションを抑制します。

ベストプラクティス

  • まずアクセスパターンからキーを設計し、その後でエンティティ属性を導き出します。
  • キー構成のずれを防ぐため、キーの構成には単一の信頼できる情報源(computeKey)を使用します。
  • 厳密な読み取り後書き込みが必要な場合に限り、.options({ consistent: true }) を使用します。
  • 実行時のリクエストパスでは、スキャンより対象を絞ったクエリを優先します。
  • 冪等性と楽観的同時実行制御のために、条件式を追加します。
  • 部分的な失敗を防ぐため、実行前にバッチ/トランザクションのサイズ制限を検証します。

制約と警告

  • DynamoDB-Toolbox v2 は AWS SDK v3 DocumentClient との統合を前提としています。
  • 明示的に範囲を限定しない限り、リクエストパスでのテーブルスキャンは避けてください。
  • 同時実行に影響される更新には、条件付き書き込みを使用します。
  • トランザクションには制限があり、単一アイテムの書き込みより遅いため、真にアトミック性が必要な場合にのみ使用します。
  • 実装前に、想定するスループットに照らしてキー設計を検証します。

参考資料

Context7 から厳選された主な参考資料は、次のファイルにあります。

  • references/api-dynamodb-toolbox-v2.md

コメント