Search code examples
aws-lambdaamazon-dynamodbaws-sdk-nodejs

DynamoDB DocumentClient returns Set of strings (SS) attribute as an object


I'm new to DynamoDB. When I read data from the table with AWS.DynamoDB.DocumentClient class, the query works but I get the result in the wrong format.

Query:

{
  TableName: "users",
  ExpressionAttributeValues: {
    ":param": event.pathParameters.cityId,
    ":date": moment().tz("Europe/London").format()
  },
  FilterExpression: ":date <= endDate",
  KeyConditionExpression: "cityId = :param"
}

Expected:

{ 
  "user": "boris",
  "phones": ["+23xxxxx999", "+23xxxxx777"]
}

Actual:

{ 
  "user": "boris",
  "phones": {
     "type": "String",
     "values": ["+23xxxxx999", "+23xxxxx777"],
     "wrapperName": "Set"
  }
}

Thanks!


Solution

  • The [unmarshall] function from the [AWS.DynamoDB.Converter] is one solution if your data comes as e.g:

    {
        "Attributes": {
          "last_names": {
            "S": "UPDATED last name"
          },
          "names": {
            "S": "I am the name"
          },
          "vehicles": {
            "NS": [
              "877",
              "9801",
              "104"
            ]
          },
          "updatedAt": {
            "S": "2018-10-19T01:55:15.240Z"
          },
          "createdAt": {
            "S": "2018-10-17T11:49:34.822Z"
          }
        }
    }
    

    Please notice the object/map {} spec per attribute, holding the attr type. Means you are using the [dynamodb]class and not the [DynamoDB.DocumentClient]. The [unmarshall] will Convert a DynamoDB record into a JavaScript object.

    Stated and backed by AWS. Ref. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/Converter.html#unmarshall-property

    Nonetheless, I faced the exact same use case, as yours. Having one only attribute, TYPE SET (NS) in my case, and I had to manually do it. Next a snippet:

     // Please notice the <setName>, which represents your set attribute name
    ddbTransHandler.update(params).promise().then((value) =>{
          value.Attributes[<setName>] = value.Attributes[<setName>].values;
          return value; // or value.Attributes
    });
    

    Cheers, Hamlet