How to initialize AWS DynamoDB on local with Nodejs
Install aws cli on your local. Follow the steps here.
Check if your installation is successful by running:
aws --version
aws-cli/2.4.8 Python/3.8.8 Linux/5.11.0-44-generic exe/x86_64.ubuntu.20 prompt/off
If the above command works, run the following with dummy values.
aws configure
AWS Access Key ID [None]: hello
AWS Secret Access Key [None]: world
Default region name [None]: local
Default output format [None]: json
Creating library for getting Database instance
const AWS = require('aws-sdk')
// TODO. pass params from CLI
AWS.config.update({
region: 'local',
endpoint: 'http://localhost:8000'
})
let dbInstance
let dbClient
export function getDbInstance() {
if (dbInstance) return dbInstance
else {
dbInstance = new AWS.DynamoDB({ apiVersion: '2012-08-10' })
return dbInstance
}
}
export function getDbClient() {
if (dbClient) return dbClient
else {
dbClient = new AWS.DynamoDB.DocumentClient({ apiVersion: '2012-08-10' })
return dbClient
}
}
So, Here we are using aws-sdk
to get access to DynamoDB api. We are exporting two methods here:
- getDbInstance
- getDbClient
You can just live with using getDbInstance
method. But using the getDbClient
makes inserting plain javascript objects much easier. I will cover each individually.
Creating Tables
const dbCreateTable = async (collectionName) => {
const dbClient = getDbInstance()
return new Promise((resolve, reject) => {
const onInsert = async function (err, data) {
if (err) {
console.error(err)
reject()
} else {
console.log(`Create Table ${collectionName} succeeded`)
resolve(0)
}
}
const params = {
TableName: collectionName,
AttributeDefinitions: [
{
AttributeName: 'id',
AttributeType: 'S'
}
],
KeySchema: [
{
AttributeName: 'id',
KeyType: 'HASH'
}
],
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
}
}
dbClient.createTable(params, onInsert)
})
}
export default dbCreateTable
Note that we are getting the database instance using getDbInstance
. This is because createTable
is part of the core DynamoDB
interface and is not avaiable as part of the DocumentClient
.
Before you can start working with tables, you need to create table by specifing properties about the table attributes, partition key and provisioned throughput.
All of these are mandatory params attributes to be specified and cannot be empty:
- AttributeDefinitions
- KeySchema
- ProvisionedThroughput
Introducing DocumentClient
Without using DocumentClient
you need to format your Item by specifying the type of each attribute you want to insert. Following is a sample that you will need to pass to insert one item into the table.
var params = {
TableName: 'CUSTOMER_LIST',
Item: {
'CUSTOMER_ID' : {N: '001'},
'CUSTOMER_NAME' : {S: 'Richard Roe'}
}
};
But this is an added overhead if you just want to deal with regular javascript objects.
With DocumentClient
you can directly use javascript object instead as follows:
var params = {
TableName: 'TABLE',
Item: {
'HASHKEY': VALUE,
'CUSTOMER_ID': 001,
'CUSTOMER_NAME': Richard Roe
}
};
Official documentation: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html
Working with the single item
I have created the following method to stardardize the insertion process using getDbClient
based put
api.
const dbInsert = async ({ id, data, collectionTitle }) => {
const dbClient = getDbClient()
return new Promise((resolve, reject) => {
const onInsert = async function (err, data) {
if (err) {
console.error(err)
reject()
} else {
console.log('PutItem succeeded')
resolve(0)
}
}
const params = {
TableName: collectionName,
Item: {
id: id,
...data
}
}
dbClient.put(params, onInsert)
})
}
export default dbInsert
You just pass the records to be inserted along with the table name and your are good.
await dbInsert(`123abc`, record, 'TABLE_NAME')
Working with the batch
I have created the following method to stardardize the bulk insertion process using getDbClient
based put
api.
async function dbBulkInsert(records, collectionName) {
const dbClient = getDbClient()
return new Promise((resolve, reject) => {
const onBatchWriteComplete = async function (err, data) {
if (err) {
console.error(err)
reject()
} else {
console.log('PutItem succeeded')
resolve(data)
}
}
const params = {
RequestItems: {
[collectionName]: records
}
}
dbClient.batchWrite(params, onBatchWriteComplete)
})
}
export default dbBulkInsert
You just pass the records to be inserted along with the table name and your are good.
await dbBulkInsert(records, 'TABLE_NAME')
Validating table creation and its content
Check tables list using cli:
aws dynamodb list-tables --endpoint-url http://localhost:8000
View table content using:
aws dynamodb scan \
--table-name <insert-table-name-here> \
--endpoint-url http://localhost:8000