I have a lambda
function to fetch some records from DynamoDB
. I setup a ddbDocClient
like in the AWS docs. I have a ddbDocClient.js
file like this:
const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const REGION = "us-west-2"
const ddbClient = new DynamoDBClient({ region: REGION });
const marshallOptions = {
convertEmptyValues: false, // false, by default.
removeUndefinedValues: false, // false, by default.
convertClassInstanceToMap: false, // false, by default.
};
const unmarshallOptions = {
wrapNumbers: false, // false, by default.
};
const translateConfig = { marshallOptions, unmarshallOptions };
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient, translateConfig);
module.exports.ddbDocClient = ddbDocClient;
Then I use it to fetch some records:
const { ddbDocClient } = require("./ddbDocClient.js");
const { QueryCommand } = require("@aws-sdk/client-dynamodb");
const listsTableName = "my_list_name";
/// Fetches lists owned by the current user
async function getListIDs(userid) {
const params = {
TableName: listsTableName,
IndexName: 'owner-index',
KeyConditionExpression: '#owner = :owner',
ExpressionAttributeNames: { "#owner": "owner" },
ExpressionAttributeValues: {":owner": { "S": userid }}
};
const command = new QueryCommand(params);
const dynamoData = await ddbDocClient.send(command);
const lists = dynamoData.Items;
console.log(lists);
}
The results I get back are like this:
[
{
things: { SS: [Array] },
owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
collaborator: { S: 'A845E8EF-956B-467D-B57B-6D959BB78C98' },
id: { S: '0C629140-6651-43E9-8D9F-3E52EBAD94F3' }
},
{
owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
things: { SS: [Array] },
collaborator: { S: 'ttttt' },
id: { S: 'xxxxx89b-009b-4ba0-80a7-12065d0908b5' }
}
]
I'm pretty sure the Document classes are supposed to unmarshall
this, or am I wrong? It even mentions middleware you can use before and after marshalling.
I am having to manually unmarshall
which needs extra steps to convert the SS
Set
's to Array
's like this:
const lists = dynamoData.Items;
// From DynamoDB JSON
var unmarshalledLists = lists.map((i) => unmarshall(i));
if (unmarshalledLists.length > 0) {
// If we have at least 1 list we need to convert the things Set to Array
unmarshalledLists.forEach(function(list) {
const things = Array.from(list.things);
list.things = things;
});
return unmarshalledLists;
} else {
// No results to return
throw("No lists found");
}
What am I doing wrong to not have it unmarshall
automatically? And it there a cleaner solution for converting the SS
results to Array
's?
You import QueryCommand from the low level client, and you also use low level syntax in your ExpressionAttributeValues. Try this:
const { ddbDocClient } = require("./ddbDocClient.js");
import { QueryCommand } from "@aws-sdk/lib-dynamodb";
const listsTableName = "my_list_name";
/// Fetches lists owned by the current user
async function getListIDs(userid) {
const params = {
TableName: listsTableName,
IndexName: 'owner-index',
KeyConditionExpression: '#owner = :owner',
ExpressionAttributeNames: { "#owner": "owner" },
ExpressionAttributeValues: {":owner": userid }
};
const command = new QueryCommand(params);
const dynamoData = await ddbDocClient.send(command);
const lists = dynamoData.Items;
console.log(lists);
}