How to fetch/scan all items from AWS dynamodb
using node.js
. I am posting my code here.
var docClient = new aws.DynamoDB.DocumentCl
A node express solution that returns the data in JSON format:
let datapack=[];
item = {
TableName: ddbTable,
FilterExpression: "aws = :e AND begins_with ( Id, :t )",
ExpressionAttributeValues: {
":t" : "contact",
":e" : aws
},
ProjectionExpression: "Id,FirstName,LastName,cEmail",
};
docClient.scan(item, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
datapack = datapack.concat(data.Items);
});
if (typeof data.LastEvaluatedKey != "undefined") {
item.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(item, onScan);
} else {
res.json(datapack);
}
}
}
Using Promises and async
const aws = require('aws-sdk');
aws.config.update({ region: 'us-east-1' });
const documentClient = new aws.DynamoDB.DocumentClient();
const scanAll = async (params) => {
let lastEvaluatedKey = 'dummy'; // string must not be empty
const itemsAll = [];
while (lastEvaluatedKey) {
const data = await documentClient.scan(params).promise();
itemsAll.push(...data.Items);
lastEvaluatedKey = data.LastEvaluatedKey;
if (lastEvaluatedKey) {
params.ExclusiveStartKey = lastEvaluatedKey;
}
}
return itemsAll;
}
Use like this
const itemsAll = scanAll(params);
The code is the same for query (just replace scan with query)
Here is an answer that will deliver indexed results rather than using an expensive scan, also in JSON format node/express. Note use of docClient.query:
datapack=[];
item = {
TableName: ddbTable,
IndexName: "cEmailIndex",
KeyConditionExpression : "aws = :e AND begins_with ( cEmail, :t )",
ExpressionAttributeValues: {
":t" : search,
":e" : aws
},
ProjectionExpression: "Id,FirstName,LastName,cEmail",
};
docClient.query(item, onScan);
function onScan(err, data) {
if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
} else {
datapack = datapack.concat(data.Items);
if (typeof data.LastEvaluatedKey != "undefined") {
item.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.query(item, onScan);
} else {
// console.log(JSON.stringify(datapack));
res.json(datapack);
}
}
}
I use promises like this:
let AWS = require('aws-sdk');
let docClient = new AWS.DynamoDB.DocumentClient();
async function dbRead(params) {
let promise = docClient.scan(params).promise();
let result = await promise;
let data = result.Items;
if (result.LastEvaluatedKey) {
params.ExclusiveStartKey = result.LastEvaluatedKey;
data = data.concat(await dbRead(params));
}
return data;
}
and to use it:
let params = {
TableName: 'Table'
};
let data = await dbRead(params);
AWS documentation example didn't work for me. @Hank approach did the trick.
Using handler inside a lambda:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({
// optional tuning - 50% faster(cold) / 20% faster(hot)
apiVersion: '2012-08-10',
sslEnabled: false,
paramValidation: false,
convertResponseTypes: false
});
const tableName = 'series';
exports.handler = async (event, context, callback) => {
let params = { TableName: tableName };
let scanResults = [];
let items;
do {
items = await docClient.scan(params).promise();
items.Items.forEach((item) => scanResults.push(item));
params.ExclusiveStartKey = items.LastEvaluatedKey;
} while (typeof items.LastEvaluatedKey != "undefined");
callback(null, scanResults);
};