6

I have this strange issue with DynamoDB where I cannot seem to update an item.

Here is my command:

TableName: 'UserTable',
Key: { UID: { S: 'h4XJj3YRxZiF7TDcGkxAhc' } },
UpdateExpression: 'SET numRatings = :numRatings',
ExpressionAttributeValues: { ':numRatings': { N: 336 } },
ReturnValues: 'UPDATED_NEW'

I have verified that the table is correct, and that the key of the table UID does indeed have the hash h4XJj3YRxZiF7TDcGkxAhc as a value. numRatings currently is equal to 1.

Here's my code:

  const params = {
    TableName: process.env.USER_TABLE_NAME!,
    Key: {
      UID: {
        S: UID
      }
    },
    UpdateExpression: 'SET numRatings = :numRatings',
    ExpressionAttributeValues: {
      ':numRatings': { N: numRatings } as unknown as AttributeValue
    },
    ReturnValues: 'UPDATED_NEW'
  } as UpdateItemCommandInput;

  try {
    const result = await dbClient.send(new UpdateItemCommand(params));
...

Yet I get this error: NUMBER_VALUE cannot be converted to String maybe I am blind but I cannot see where this conversion could be taking place.

I am using TypeScript and AWS-SDK 3.54.0

If anyone is able to point out what I am doing wrong I would greatly appreciate it.

Item

Jonathan
  • 105
  • 1
  • 7
  • How did you create `dbClient`? Is it the regular low-level SDK client or is it a Document Client? Presume the former. – jarmod Mar 16 '22 at 00:20
  • 1
    And try ``':numRatings': { N: `${numRatings}` }`` – jarmod Mar 16 '22 at 00:29
  • That worked thank you! Very strange that the value needs to be a string despite the key being a number. In case anyone in the future needs it, dbClient: `import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; const dbClient = new DynamoDBClient({});` this is how I've done it for many other lambdas – Jonathan Mar 16 '22 at 09:35

1 Answers1

20

Per the AttributeValue documentation:

Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.

So, because you are using the low-level DynamoDB client, you need to send numeric values as type N but the value must be a string:

':numRatings': { N: `${numRatings}` }

If you use the higher-level DocumentClient, which automatically performs marshalling of data between JavaScript objects and DynamoDB attribute values, then you can use:

':numRatings': numRatings
jarmod
  • 71,565
  • 16
  • 115
  • 122