dynamodb-toolbox-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDynamoDB-Toolbox v2 Patterns (TypeScript)
DynamoDB-Toolbox v2 模式(TypeScript)
Overview
概述
This skill provides practical TypeScript patterns for using DynamoDB-Toolbox v2 with AWS SDK v3 DocumentClient. It focuses on type-safe schema modeling, command usage, and production-ready single-table design.
.build()本技能提供了在TypeScript中结合AWS SDK v3 DocumentClient使用DynamoDB-Toolbox v2的实用模式,重点关注类型安全的Schema建模、.build()命令的使用,以及可用于生产环境的单表设计。
When to Use
适用场景
- Defining DynamoDB tables and entities with strict TypeScript inference
- Modeling schemas with ,
item,string,number,list,set, andmaprecord - Implementing ,
GetItem,PutItem,UpdateItemviaDeleteItem.build() - Building query and scan access paths with primary keys and GSIs
- Handling batch and transactional operations
- Designing single-table systems with computed keys and entity patterns
- 使用严格的TypeScript推断定义DynamoDB表和实体
- 使用、
item、string、number、list、set和map建模Schemarecord - 通过实现
.build()、GetItem、PutItem、UpdateItem操作DeleteItem - 基于主键和GSI构建查询和扫描访问路径
- 处理批量和事务操作
- 使用计算键和实体模式设计单表系统
Instructions
操作步骤
- Start from access patterns: identify read/write queries first, then design keys.
- Create table + entity boundaries: one table, multiple entities if using single-table design.
- Define schemas with constraints: apply ,
.key(),.required(),.default(),.transform()..link() - Use commands everywhere: avoid ad-hoc command construction for consistency and type safety.
.build() - Add query/index coverage: validate GSI/LSI paths for each required access pattern.
- Use batch/transactions intentionally: batch for throughput, transactions for atomicity.
- Keep items evolvable: use optional fields, defaults, and derived attributes for schema evolution.
- 从访问模式入手:先确定读写查询,再设计键。
- 创建表和实体边界:如果使用单表设计,一个表对应多个实体。
- 定义带约束的Schema:使用、
.key()、.required()、.default()、.transform()。.link() - 全程使用.build()命令:为了一致性和类型安全,避免临时构造命令。
- 添加查询/索引覆盖:验证每个所需访问模式的GSI/LSI路径。
- 合理使用批量/事务:批量操作提升吞吐量,事务操作保证原子性。
- 保持项目可演进:使用可选字段、默认值和派生属性实现Schema演进。
Examples
示例
Install and Setup
安装与设置
bash
npm install dynamodb-toolbox @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodbtypescript
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
});bash
npm install dynamodb-toolbox @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodbtypescript
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
});Entity Schema with Modifiers and Complex Attributes
带修饰符和复杂属性的实体Schema
typescript
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}`
})
});typescript
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 Commands
.build().build()
CRUD命令
.build()typescript
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: 'A@Example.com' })
.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();typescript
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: 'A@Example.com' })
.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();Query and Scan Patterns
查询与扫描模式
typescript
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();typescript
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();Batch and Transaction Workflows
批量与事务工作流
typescript
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: 'u2@example.com' }),
UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u3', email: 'u3@example.com' })
)
.send();
await AppTable.build(TransactWriteCommand)
.requests(
UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u4', email: 'u4@example.com' }),
UserEntity.build(UpdateItemCommand).item({ tenantId: 't1', userId: 'u1', loginCount: $add(1) })
)
.send();typescript
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: 'u2@example.com' }),
UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u3', email: 'u3@example.com' })
)
.send();
await AppTable.build(TransactWriteCommand)
.requests(
UserEntity.build(PutItemCommand).item({ tenantId: 't1', userId: 'u4', email: 'u4@example.com' }),
UserEntity.build(UpdateItemCommand).item({ tenantId: 't1', userId: 'u1', loginCount: $add(1) })
)
.send();Single-Table Design Guidance
单表设计指南
- Model each business concept as an entity with strict schema.
- Keep PK/SK predictable and composable (,
TENANT#,USER#).ORDER# - Encode access paths into GSI keys, not in-memory filters.
- Prefer append-only timelines for audit/history data.
- Keep hot partitions under control with scoped partitions and sharding where needed.
- 将每个业务概念建模为带有严格Schema的实体。
- 保持PK/SK可预测且可组合(如、
TENANT#、USER#)。ORDER# - 将访问路径编码到GSI键中,而非内存过滤器。
- 对于审计/历史数据,优先使用追加式时间线。
- 通过范围分区和分片(如有需要)控制热分区。
Best Practices
最佳实践
- Design keys from access patterns first, then derive entity attributes.
- Keep one source of truth for key composition () to avoid drift.
computeKey - Use only where strict read-after-write is required.
.options({ consistent: true }) - Prefer targeted queries over scans for runtime request paths.
- Add conditional expressions for idempotency and optimistic concurrency control.
- Validate batch/transaction size limits before execution to avoid partial failures.
- 先从访问模式设计键,再推导实体属性。
- 保持键组合的单一可信来源(),避免不一致。
computeKey - 仅在需要严格的写后读一致性时使用。
.options({ consistent: true }) - 对于运行时请求路径,优先使用定向查询而非扫描。
- 添加条件表达式以实现幂等性和乐观并发控制。
- 在执行前验证批量/事务大小限制,避免部分失败。
Constraints and Warnings
约束与警告
- DynamoDB-Toolbox v2 relies on AWS SDK v3 DocumentClient integration.
- Avoid table scans in request paths unless explicitly bounded.
- Use conditional writes for concurrency-sensitive updates.
- Transactions are limited and slower than single-item writes; use only for true atomic requirements.
- Validate key design against target throughput before implementation.
- DynamoDB-Toolbox v2依赖于AWS SDK v3 DocumentClient的集成。
- 除非明确限制范围,否则避免在请求路径中使用表扫描。
- 对并发敏感的更新使用条件写入。
- 事务有数量限制且比单条写入慢;仅在真正需要原子性时使用。
- 在实现前验证键设计是否符合目标吞吐量。
References
参考资料
Primary references curated from Context7 are available in:
references/api-dynamodb-toolbox-v2.md
由Context7整理的主要参考资料位于:
references/api-dynamodb-toolbox-v2.md