Quick Tour
OneTable is the most evolved API for DynamoDB. It provides a high-level, elegant dry syntax while still enabling full access to DynamoDB API.
OneTable works with AWS V2 and V3 SDKs for JavaScript and TypeScript. For TypeScript, OneTable will create fully typed entities from your data schemas automatically.
To see OneTable in action, take this quick tour of OneTable which demonstrates importing, configuring and basic operation of OneTable.
Import OneTable
To start, import the OneTable library.
| import {Table} from 'dynamodb-onetable'
|
Import the AWS SDK
If you are not using ES modules or TypeScript, use require
to import the libraries.
If you are using the AWS SDK V3, import the AWS V3 DynamoDBClient
class. Then create a DynamoDBClient
instance.
| import {DynamoDBClient} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient(params)
|
If you are using the legacy AWS SDK V2, import the AWS DynamoDB
class and create a DocumentClient
instance.
| import DynamoDB from 'aws-sdk/clients/dynamodb'
const client = new DynamoDB.DocumentClient(params)
|
Note: you can use the Table.setClient API to defer setting the client or replace the client at any time.
Initialize your OneTable Table
instance and define your application entities via a OneTable schema.
| const table = new Table({
client: client,
name: 'MyTable',
schema: MySchema,
})
|
Data Modeling
OneTable models your application entities via a OneTable schema.
The schema defines your entities and their attributes and how they will be stored in your DynamoDB table. The schema also defines the table indexes. Here is a sample schema:
| const MySchema = {
format: 'onetable:1.1.0',
version: '0.0.1',
indexes: {
primary: { hash: 'pk', sort: 'sk' },
gs1: { hash: 'gs1pk', sort: 'gs1sk', follow: true },
ls1: { sort: 'id', type: 'local' },
},
models: {
Account: {
pk: { type: String, value: 'account#${id}' },
sk: { type: String, value: 'account#' },
id: { type: String, generate: 'ulid', validate: /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/i },
name: { type: String, required: true },
status: { type: String, default: 'active' },
zip: { type: String },
},
User: {
pk: { type: String, value: 'account#${accountName}' },
sk: { type: String, value: 'user#${email}', validate: EmailRegExp },
id: { type: String, required: true },
accountName: { type: String, required: true, encode: 'pk' },
email: { type: String, required: true, encode: 'sk' },
firstName: { type: String, required: true },
lastName: { type: String, required: true },
username: { type: String, required: true },
role: { type: String, enum: ['user', 'admin'], required: true, default: 'user' },
balance: { type: Number, default: 0 },
gs1pk: { type: String, value: 'user-email#${email}' },
gs1sk: { type: String, value: 'user#' },
}
},
params: {
'isoDates': true,
'separator': '#',
'timestamps': true,
},
}
|
For each model, you define the entity attributes and their type and other properties.
Get a Model
To interact with DynamoDB, get a model for the application entity.
| const model = table.getModel('Account')
|
If using TypeScript, see TypeScript Tour.
Create an Item
To create
| let account = await Account.create({
id: '8e7bbe6a-4afc-4117-9218-67081afc935b',
name: 'Acme Airplanes',
})
|
This will write the following to DynamoDB:
| {
pk: 'account:8e7bbe6a-4afc-4117-9218-67081afc935b',
sk: 'account:98034',
id: '8e7bbe6a-4afc-4117-9218-67081afc935b',
name: 'Acme Airplanes',
status: 'active',
zip: '98034',
created: 1610347305510,
updated: 1610347305510,
}
|
Get an Item
| let account = await Account.get({
id: '8e7bbe6a-4afc-4117-9218-67081afc935b',
})
|
which will return:
| {
id: '8e7bbe6a-4afc-4117-9218-67081afc935b',
name: 'Acme Airplanes',
status: 'active',
zip: '98034',
}
|
Use a Secondary Index:
| let user = await User.get({email: 'user@example.com'}, {index: 'gs1'})
|
Find Items
To find a set of items:
| let users = await User.find({accountId: account.id})
let adminUsers = await User.find({accountId: account.id, role: 'admin'})
let users = await User.find({accountId: account.id}, {
where: '${balance} > {100.00}'
})
// Get a count of matching users without returning the actual items
let users = await User.find({accountId: account.id, role: 'admin'}, {count: true})
let count = users.count
|
Update an Item
| await User.update({id: userId, balance: 50})
await User.update({id: userId}, {add: {balance: 10.00}})
await User.update({id: userId}, {set: {status: '{active}'}})
await User.update({id: userId}, {push: {tasks: 'Learn DynamoDB'}})
|
Transactional Updates
| let transaction = {}
await Account.update({id: account.id, status: 'active'}, {transaction})
await User.update({id: user.id, role: 'user'}, {transaction})
await table.transact('write', transaction)
|
More
There is so much more including
- TypeScript type checking of APIs and schema data
- Validations
- Support for required and unique attributes
- Batch updates
- Automatic extra encryption for sensitive attributes
- Detailed Metrics
- Multi-page response aggregation
- Create and manage tables
- Database migrations
- Integrated logging of requests and responses