DEV Community

Nikola Bintev
Nikola Bintev

Posted on

DynamoDB QueryCommand in AWS SDK JS v3

The AWS SDK for JavaScript v3 introduces the concept of modular architecture which encapsulates each service into a separate package. It means that you no longer need to import the whole AWS SDK package, but only the services that you need to use. This significantly reduces the size of your application.

It also comes with a new middleware stack to control the lifecycle of an operation call and TypeScript support. You can read more about it here.

Despite the nice features, migrating from v2 to v3 comes with some complexity that we'd like to highlight.

Marshalled/Unmarshalled data

The data that is sent as input to a given DynamoDb command must be marshalled. Marshalling is simply adding the type of the value to the JSON object

JSON object:

ExpressionAttributeValues: {
  ':username': 'somename',
  ':email': 'some@name.com'
},
Enter fullscreen mode Exit fullscreen mode

Marshalled JSON object:

ExpressionAttributeValues: {
  ':username': {S: 'somename'},
  ':email': {S: 'some@name.com'}
},
Enter fullscreen mode Exit fullscreen mode

Respectively, the command's response must be unmarshalled.

Examples

The examples are based on the assumption that we have a users table that has a partition key called username and sort key - email.

Note: The AWS credentials are not covered in the examples below.

Example 1: Send a query command with manually marshalled data.

  1. Import DynamoDBClient and QueryCommand modules from @aws-sdk/client-dynamodb
  2. The QueryCommand expects ExpressionAttributeValues to be a marshalled JSON object, so we explicitly set the type of the values
  3. The commands are executed by using the send method of the DynamoDBClient which accepts the command as the first argument.
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";

export const dynamoDbClient = new DynamoDBClient({region: 'eu-central-1'});

// The ExpressionAttributeValues must be marshalled,
// so the type of the values are explicitly set.
const params = {
  TableName: 'users',
  KeyConditionExpression: 'username = :username and email = :email',
  ExpressionAttributeValues: {
    ':username': {S: 'somename'},
    ':email': {S: 'some@name.com'}
  },
};

try {
  const response = await dynamoDbClient.send(new QueryCommand(params));
}
catch (e) {
  console.error(e.message);
}
Enter fullscreen mode Exit fullscreen mode

Example 2: Send a query command by using a utility module to marshall/unmarshall the data.

Instead of explicitly specifying the type of the values for the ExpressionAttributeValues key, we can use the marshall/unmarshall modules that come from the @aws-sdk/util-dynamodb package.

import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';

export const dynamoDbClient = new DynamoDBClient({region: 'eu-central-1'});

// The ExpressionAttributeValues must be marshalled,
// so the type of the values are explicitly set.
const params = {
  TableName: 'users',
  KeyConditionExpression: 'username = :username and email = :email',
  ExpressionAttributeValues: marshall({
    ':username': 'somename',
    ':email': 'some@name.com'
  }),  
};

try {
  const response = await dynamoDbClient.send(new QueryCommand(params));
}
catch (e) {
  console.error(e.message);
}
Enter fullscreen mode Exit fullscreen mode

Example 3: Send a query command by using @aws-sdk/lib-dynamodb

The @aws-sdk/lib-dynamodb automatically handles the necessary marshalling and unmarshalling of the data.

The only difference is that the QueryCommand is imported from the @aws-sdk/lib-dynamodb package instead of @aws-sdk/client-dynamodb and no manual marshalling is needed.

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { QueryCommand } from '@aws-sdk/lib-dynamodb';

export const dynamoDbClient = new DynamoDBClient({region: 'eu-central-1'});

// The ExpressionAttributeValues will be automatically
// marshalled by the @aws-sdk/lib-dynamodb.
const params = {
  TableName: 'users',
  KeyConditionExpression: 'username = :username and email = :email',
  ExpressionAttributeValues: {
    ':username': 'somename',
    ':email': 'some@name.com'
  },
};

try {
  const response = await dynamoDbClient.send(new QueryCommand(params));
}
catch (e) {
  console.error(e.message);
}
Enter fullscreen mode Exit fullscreen mode

Bottom line

The AWS SDK for JavaScript v3 introduces the ES6 modules which can reduce the size of our applications. It also comes with some nice features like a new middleware stack and TypeScript support, however, migrating from v2 to v4 might be a bit tricky and requires code changes.

Top comments (2)

Collapse
 
nikolabintev profile image
Nikola Bintev

Hi @debnathweb,

The article itself does not cover the credentials management. You can do it with an access key and secret access key, or you can assume a role with the needed permissions.

Collapse
 
debnathweb profile image
Debnath

how to with cognito identity pool creadential
DynamoDBClient({region: 'eu-central-1'});