DynamoDB With LocalStack And The AWS CDK (Part 2)
Published: Aug 10, 2021
Last updated: Aug 10, 2021
Today's post will demonstrate usage of DynamoDB Toolbox
This post will continue on from the work done yesterday in part one
Be sure to check that out to understand where we are up to.
The final code for today's post will be in my GitHub repository
Prerequisites
Getting started
Let's clone our code from part one
$ git clone https://github.com/okeeffed/dynamodb-with-localstack-and-the-aws-cdk dynamodb-with-localstack-and-the-aws-cdk-part-two $ cd dynamodb-with-localstack-and-the-aws-cdk-part-two $ rm package-lock.json $ rm -rf .git $ git init $ npm i # Add the packages that we need for today $ npm i dynamodb-toolbox aws-sdk faker $ npm i --save-dev @types/faker # Create some files for today's work $ mkdir src scripts $ touch src/customer.ts scripts/putCustomers.ts scripts/getCustomers.ts
At this stage, we will have all the tools we need to get started.
Using DynamoDB Toolbox to put and get customers
Inside of src/customer.ts
, add the following:
import { DynamoDB } from "aws-sdk"; import { Entity, Table } from "dynamodb-toolbox"; import * as faker from "faker"; // Require AWS SDK and instantiate DocumentClient const DocumentClient = new DynamoDB.DocumentClient({ endpoint: `http://localhost:4566`, }); // Instantiate a table const MyTable = new Table({ // Specify table name (used by DynamoDB) name: "my-table", // Define partition and sort keys partitionKey: "pk", sortKey: "sk", // Add the DocumentClient DocumentClient, }); type Customer = { pk: number; sk: string; name: string; company: string; age: number; status: string; data_added: string; }; const Customer = new Entity<Customer>({ // Specify entity name name: "Customer", // Define attributes attributes: { id: { partitionKey: true }, // flag as partitionKey sk: { hidden: true, sortKey: true }, // flag as sortKey and mark hidden name: { map: "data" }, // map 'name' to table attribute 'data' co: { alias: "company" }, // alias table attribute 'co' to 'company' age: { type: "number" }, // set the attribute type status: ["sk", 0], // composite key mapping date_added: ["sk", 1], // composite key mapping }, // Assign it to our table table: MyTable, }); export const addCustomer = async (): Promise<void> => { const item = { id: faker.datatype.uuid(), name: faker.name.findName(), company: faker.company.companyName(), age: Math.floor(Math.random() * 100), status: "active", date_added: "2020-04-24", }; // Use the 'put' method of Customer await Customer.put(item); }; export const scanTable = async (): Promise<any> => { const res = await MyTable.scan({ limit: 10, }); return res; };
In this file, we are setting up the DynamoDB.DocumentClient
to point towards LocalStack, then creating a table with the toolbox based on our tableName
from the stack we built yesterday, as well as our partitionKey
and soretKey
Within the new Entity
invocation, we are defining what our table will hold.
If it important to know that id
will map to the table's partition key pk
and status
and date_added
will combine to create the sk
. For example, a status
of active
and a date_added
of 2020-04-24
will create the sk
active#2020-04-24
.
While this post won't go into the "do and don't do" of single-table design, we will use that to illustrate how to interact with the LocalStack table.
We have two helper functions: addCustomer
and scanTable
. We will use these to demonstrate adding some customers (with fake date through faker
) and scanning the table.
Writing the scripts
Inside of scripts/putCustomers.ts
, add the following:
import { addCustomer } from "../src/customer"; async function main() { for (let i = 0; i < 100; i++) { // yes, we are doing this the slow way for the demo await addCustomer(); } console.log("Done"); } main();
Inside of scripts/getCustomers.ts
, add the following:
import { scanTable } from "../src/customer"; async function main() { const res = await scanTable(); console.log(res); } main();
In order to be able to run these scripts, we will need to add a new script to package.json
:
{ "scripts": { "ts": "ts-node" } }
This will allow us to run our TypeScript files.
Running our scripts with LocalStack
At this stage, ensure that LocalStack is running and that the table has been deploy through the AWS CDK:
# In one terminal tab $ docker compose up # In another tab when LocalStack is ready $ npm run local synth && npm run local deploy
Once everything is up and ready, we can add our customers:
$ npm run ts scripts/putCustomers.ts Done
Note: If you have issues, check that you have your AWS credentials and region in your environment variables.
To confirm that we can interact with our table as expected, we can now run our scan and confirm that the table does in fact have our generated users!
$ npm run ts scripts/getCustomers.ts > aws-cdk-with-typescript-foundations@0.1.0 ts > ts-node "scripts/getCustomers.ts" { Items: [ { created: '2021-08-09T22:18:21.153Z', date_added: '2020-04-24', name: 'Bert Upton', modified: '2021-08-09T22:18:21.153Z', id: '572657d5-41fb-45d8-8747-75fde1c5c26f', company: 'Flatley Inc', age: 17, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:23.059Z', date_added: '2020-04-24', name: 'Lloyd Beer', modified: '2021-08-09T22:18:23.059Z', id: '8724af8c-c448-4448-83b1-9c3c3c38b501', company: 'McGlynn Inc', age: 10, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:22.641Z', date_added: '2020-04-24', name: 'Terrell Donnelly', modified: '2021-08-09T22:18:22.641Z', id: '384efa80-debd-406f-b2fc-88413c38b4f6', company: 'Bode, Cummings and Heathcote', age: 47, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:24.709Z', date_added: '2020-04-24', name: 'Doreen Sanford', modified: '2021-08-09T22:18:24.709Z', id: '58d0901f-4f1b-4664-bb05-5e3248235eeb', company: 'Jenkins, Gutmann and Trantow', age: 97, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:23.877Z', date_added: '2020-04-24', name: 'Alice Connelly', modified: '2021-08-09T22:18:23.877Z', id: 'b04f40d8-b775-4f2e-b0bc-688224a6a522', company: 'Rowe - Jenkins', age: 71, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:24.630Z', date_added: '2020-04-24', name: 'Lloyd Wunsch', modified: '2021-08-09T22:18:24.630Z', id: '040d088c-57e1-4d3d-a8ac-34370b0d5f48', company: 'Cummings Group', age: 4, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:23.646Z', date_added: '2020-04-24', name: 'Jermaine Nikolaus', modified: '2021-08-09T22:18:23.646Z', id: '8dd4ae85-a123-4bd2-9af0-e0099eec7273', company: 'Barrows, Powlowski and Feeney', age: 89, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:24.753Z', date_added: '2020-04-24', name: 'Tasha DuBuque', modified: '2021-08-09T22:18:24.753Z', id: '2640bf11-ad67-4a35-b207-403c362041a2', company: 'Metz Group', age: 35, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:21.733Z', date_added: '2020-04-24', name: 'Mr. Terry Gorczany', modified: '2021-08-09T22:18:21.733Z', id: '241d1d2c-b93c-4b8a-a1f0-702686c3cef9', company: 'Schumm - Daniel', age: 36, entity: 'Customer', status: 'active' }, { created: '2021-08-09T22:18:24.550Z', date_added: '2020-04-24', name: 'Reginald Osinski', modified: '2021-08-09T22:18:24.550Z', id: 'd5892a47-9850-4ba1-aa7f-298915eaad37', company: 'Lueilwitz and Sons', age: 26, entity: 'Customer', status: 'active' } ], Count: 10, ScannedCount: 10, LastEvaluatedKey: { sk: 'active#2020-04-24', pk: 'd5892a47-9850-4ba1-aa7f-298915eaad37' }, next: [Function: next] }
When we scan the table, you will notice that the users are all mapped back to their expected values as defined in our Table
.
Teardown
As per usual, once you are done we can tear down the stack:
$ npm run local destroy > aws-cdk-with-typescript-foundations@0.1.0 local > cdklocal "destroy" Are you sure you want to delete: AwsCdkWithTypescriptFoundationsStack (y/n)? y AwsCdkWithTypescriptFoundationsStack: destroying... ✅ AwsCdkWithTypescriptFoundationsStack: destroyed
Summary
Today's post demonstrated how to interact with the DynamoDB table that we created on LocalStack through the DynamoDB toolbox.
Albeit simple, we generated 100 users in our table and scanned for the first ten.
Resources and further reading
Photo credit: waldemarbrandt67w
Dennis O'Keeffe
Melbourne, Australia
1,200+ PEOPLE ALREADY JOINED ❤️️
Get fresh posts + news direct to your inbox.
No spam. We only send you relevant content.
DynamoDB With LocalStack And The AWS CDK (Part 2)
Introduction