Search code examples
amazon-web-servicesaws-lambdaamazon-dynamodbdynamodb-queries

Why do AWS JavaScript SDK calls to DynamoDB fail with native data types?


When I try to query Amazon DynamoDB using native JavaScript data types it fails (e.g. :zipcode below). For example, the following code fails with Error while fetching data: TypeError: Cannot read properties of undefined (reading '0').

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

const client = new DynamoDBClient({});

await client.send(
  new QueryCommand({
    TableName: tableName,
    KeyConditionExpression: "zipcode = :zipcode ",
    ExpressionAttributeValues: {
      ":zipcode": "11111",
    },
    ConsistentRead: true,
  })
);

But the below code works.

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

const client = new DynamoDBClient({});

docClient.send(
  new QueryCommand({
    TableName: tableName,
    KeyConditionExpression: "zipcode = :zipcode ",
    ExpressionAttributeValues: {
      ":zipcode": { "S": "11111" },
    },
    ConsistentRead: true,
  })
);

What is this { "S": <value> } syntax and why is it needed?


Solution

  • Your second version of the syntax is correct. DynamoDB needs to know what data type you're sending it. The S in { "S": "1111" } indicates that you're sending a string. You can see a full list of the data type descriptors here.

    Optionally, if you want to use your first syntax, you can use the Document Client.

    V3

    import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
    import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";
    
    const client = new DynamoDBClient({});
    const docClient = DynamoDBDocumentClient.from(client);
    
    docClient.send(
      new QueryCommand({
        TableName: tableName,
        KeyConditionExpression: "zipcode = :zipcode",
        ExpressionAttributeValues: {
          ":zipcode": "11111",
        },
        ConsistentRead: true,
      })
    );
    

    V2

    import * as AWS from "aws-sdk";
    
    var params = {
      TableName: "Table",
      KeyConditionExpression: "zipcode = :zipcode",
      ExpressionAttributeValues: {
        ":zipcode": "11111",
      }
    };
    
    var documentClient = new AWS.DynamoDB.DocumentClient();
    
    documentClient.query(params, function(err, data) {
       if (err) console.log(err);
       else console.log(data);
    });
    

    The Code Library for the JS SDK has multiple examples showcasing this syntax.