DynamoDB Scan with Lambda not returning elements - node.js

I have a Lambda with the following code:
// Load the AWS SDK for Node.js.
var AWS = require("aws-sdk");
// Set the AWS Region.
AWS.config.update({ region: "us-east-2" });
exports.handler = function(event, context, callback) {
// Create DynamoDB service object.
var ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
var params = {
TableName: "Ranking",
ProjectionExpression: "#username, Score, Duration",
FilterExpression: "#username = :username",
ExpressionAttributeNames: {
"#username": "Username",
},
ExpressionAttributeValues: {
":username": {
S: 'Alberto'
},
}
};
let toReturn = [];
ddb.scan(params, function (err, data) {
if (err) {
toReturn = err
} else {
toReturn = data.Items;
}
});
let response = {
statusCode: 200,
body: JSON.stringify(toReturn)
};
callback(null, response)
};
However I always see [] as response...
My current DB has the following records:
So my question is... why I don't get back that item?

Since you are using callbacks, your code should be as below. Also Duration is reserved keyword, so it also needs to be modified as below:
// Load the AWS SDK for Node.js.
var AWS = require("aws-sdk");
// Set the AWS Region.
AWS.config.update({ region: "us-east-2" });
exports.handler = function(event, context, callback) {
// Create DynamoDB service object.
var ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
var params = {
TableName: "Ranking",
FilterExpression: "#username = :username",
ProjectionExpression: "#username, Score, #duration",
ExpressionAttributeNames: {
"#username": "Username",
"#duration": "Duration",
},
ExpressionAttributeValues: {
":username": {
S: 'Alberto'
},
}
};
ddb.scan(params, function (err, data) {
if (err) {
callback(null, err)
} else {
callback(null, data.Items)
}
});
};

Related

My Lambda ends before code is complete - node.js

I know this has been asked in various ways before, but I can't figure it out. I'm still very new to node.js and lambda. This code will work if I run the lambda twice, but never runs to completion the first time. This also works fine if I run this from a local IDE by adding
exports.handler();
to the end of the code block.
The code queries DynamoDB for results and then attempts to delete those records from Dynamo. The query part seems to work every time, but the deletion part fails to happen on the first invocation.
I can't seem to figure out what changes are necessary to for lambda to wait until all of my processes are complete.
Thanks in advance.
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({ region: 'us-east-2' });
exports.handler = async (event) => {
// Create DynamoDB service object
const ddb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
const documentClient = new AWS.DynamoDB.DocumentClient({ region: "us-east-2" });
const tablename = process.env.table_name;
let dynapromises = [];
let params = {
ExpressionAttributeValues: {
':offNum': { S: process.env.cost_center },
':s': { N: '2' }
},
ExpressionAttributeNames: {
"#notif_status": "status"
},
KeyConditionExpression: 'officeNumber = :offNum',
TableName: tablename,
IndexName: 'officeNumberIndex',
ProjectionExpression: "notificationNumber",
FilterExpression: '(attribute_not_exists(#notif_status) or #notif_status = :s) and attribute_not_exists(statusTimes)'
};
let qresults = await ddb.query(params).promise();
console.log("Count of notifs again " + qresults.Items.length);
qresults.Items.forEach(function(element, index, array) {
console.log(element.notificationNumber.S);
let delparams = {
TableName: tablename,
ReturnValues: "ALL_OLD",
Key: {
notificationNumber: {
S: element.notificationNumber.S
}
}
};
dynapromises.push(ddb.deleteItem(delparams).promise().then(function(data) {
console.log("Deleted Record:"+ JSON.stringify(data)); // successful response
}, function(error) {
console.log(error, error.stack); // an error occurred
}));
console.log("deletion parameters " + JSON.stringify(delparams));
});
Promise.all(dynapromises).then(res => {
console.log("All promises done");
});
return qresults.Items.length;
};
The issue is in that you are returning before all the promises are completed, you need to move the return qresults.Items.length; inside the last then.
try with this code:
** UPDATE: Change the snippet with the working code **
// Load the AWS SDK for Node.js
const AWS = require('aws-sdk');
// Set the region
AWS.config.update({ region: 'us-east-2' });
exports.handler = async (event) => {
// Create DynamoDB service object
const ddb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
const documentClient = new AWS.DynamoDB.DocumentClient({ region: "us-east-2" });
const tablename = process.env.table_name;
let params = {
ExpressionAttributeValues: {
':offNum': { S: process.env.cost_center },
':s': { N: '2' }
},
ExpressionAttributeNames: {
"#notif_status": "status"
},
KeyConditionExpression: 'officeNumber = :offNum',
TableName: tablename,
IndexName: 'officeNumberIndex',
ProjectionExpression: "notificationNumber",
FilterExpression: '(attribute_not_exists(#notif_status) or #notif_status = :s) and attribute_not_exists(statusTimes)'
};
let qresults = await ddb.query(params).promise();
console.log("Count of notifs again " + qresults.Items.length);
const dynapromises = qresults.Items.map( async element => {
let delparams = {
TableName: tablename,
ReturnValues: "ALL_OLD",
Key: {
notificationNumber: {
S: element.notificationNumber.S
}
}
};
try {
console.log("deletion parameters " + JSON.stringify(delparams));
const data = await ddb.deleteItem(delparams).promise();
console.log( "Deleted Record:"+ JSON.stringify(data) );
} catch ( err ) {
console.log(error, error.stack); // an error occurred
}
} )
await Promise.all(dynapromises)
console.log("All promises done");
return qresults.Items.length;
};
The code that #pepo posted is performing the Dynamo deletions on the first invocation of the Lambda. Thanks for his work and the responses from everyone.

AWS Lambda using s3 getObject function and putItem function to insert it into DynamoDB but nothing happens

this is the node.js code:
'use strict';
const AWS = require("aws-sdk");
AWS.config.update({
region: 'eu-west-1'});
const docClient = new AWS.DynamoDB.DocumentClient();
const tableName = 'Fair';
const s3 = new AWS.S3();
exports.handler = async (event) => {
var getParams = {
Bucket: 'dataforfair', //s3 bucket name
Key: 'fairData.json' //s3 file location
}
const data = await s3.getObject(getParams).promise()
.then( (data) => {
//parse JSON
let fairInformations = JSON.parse(data.Body.toString());
fairInformations.forEach(function(fairInformationEntry) {
console.log(fairInformationEntry);
var params = {
TableName: tableName,
Item: {
"year": fairInformationEntry.year,
"fairName": fairInformationEntry.fairName,
"info": fairInformationEntry.info
}
};
docClient.put(params, function(err, data) {
console.log('*****test');
if (err) {
console.error("Unable to add fairInformation", fairInformationEntry.fairName, ". Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("PutItem succeeded:", fairInformationEntry.fairName);
}
});
});
})
.catch((err) => {
console.log(err);
});
const response = {
statusCode: 200,
body: JSON.stringify(data),
};
return response;
};
Hello everyone,
I want to put the data into the Dynamo DB after getting the JSON file from the s3 Bucket. Getting the JSON works and the console.log(fairInformationEntry); is also still triggered, but the docClient.put() never gets called. I am getting no error, nothing. I do not know what is wrong and why it is not working. I have the right IAM role and access to everything I need.
I hope you can help me!
The problem is mixup of promise, callback and async/await. You are also trying to do asynchronous operation inside foreach. The code should look something like this
"use strict";
const AWS = require("aws-sdk");
AWS.config.update({
region: "eu-west-1"
});
const docClient = new AWS.DynamoDB.DocumentClient();
const tableName = "Fair";
const s3 = new AWS.S3();
exports.handler = async event => {
var getParams = {
Bucket: "dataforfair", //s3 bucket name
Key: "fairData.json" //s3 file location
};
const data = await s3.getObject(getParams).promise();
//parse JSON
let fairInformations = JSON.parse(data.Body.toString());
await Promise.all(
fairInformations.map(fairInformationEntry => {
console.log(fairInformationEntry);
var params = {
TableName: tableName,
Item: {
year: fairInformationEntry.year,
fairName: fairInformationEntry.fairName,
info: fairInformationEntry.info
}
};
return docClient.put(params).promise();
})
);
const response = {
statusCode: 200,
body: JSON.stringify(data)
};
return response;
};
Hope this helps

AWS Lambda function written in nodejs is not updating my DynamoDB

I'm a student who is new to AWS, but I have reached a blocker....
I am trying to use a lambda function to update an attribute for an item in my dynamodb table. The lambda function is being triggered, but for some reason I am unable to update the item.
I was able to successfully delete the item from the dynamodb, but when I try to update an attribute for an item nothing happens.
The attribute human_confirmed is not updating to true after the function executes. I've been trying different things I've found on Google, but nothing is working :(
console.log('Loading function');
var AWS = require('aws-sdk');
exports.handler = (event, context, callback) => {
AWS.config.update({
region: "us-east-1"
});
var dynamodb = new AWS.DynamoDB.DocumentClient();
var instance = event.instanceID;
var InstanceName = instance;
var params = {
TableName: "reminders",
Key: {
"instanceID": {
S: InstanceName
},
},
UpdateExpression: 'SET #a = :x',
ExpressionAttributeNames: {'#a' : 'human_confirmed'},
ExpressionAttributeValues: {
':x' : 'true',
},
ReturnValues:"UPDATED_NEW"
};
dynamodb.update(params, function(err, data) {
if (err)
callback(err, null); // an error occurred
else
callback(null, data); // successful response
});
callback(null, "Updating resource from reminder table: " + InstanceName + ".... The system will no longer contain automated emails about this resource's tags!");
};
make sure you have this configuration: dynamodb:PutItem in your serverless.yml file
iamRoleStatements:
- Effect: "Allow"
Action:
- "dynamodb:PutItem"
Resource: "*"
Thanks for the help #kaxi1993
I believe my IAMRole permissions were correct. Here was the code that worked for me.
'use strict';
console.log('Loading function');
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = (event, context, callback) => {
AWS.config.update({
region: 'us-east-1'
});
var instance = event.instanceID;
var params = {
TableName: 'reminders',
Key: {
'instanceID': {
S: instance
}
},
UpdateExpression: 'set human_confirmed = :x',
ExpressionAttributeValues: {
':x': {S: 'true'},
},
ReturnValues: 'UPDATED_NEW'
};
dynamodb.updateItem(params, function(err, data) {
if (err)
callback(err, null); // an error occurred
else
callback(null, data); // successful response
});
callback(null, 'Updating instance from reminder table: ' + instance + '.... The system will no longer contain automated emails about this resource.');
};

How do I configure the Amazon DynamoDB region in Nodejs?

I have the following code for adding an item to Amazon DynamoDB . I have set the region to ap-south-1, but the item is getting added to us-east-1 region.
AWS.config.update({
region: "ap-south-1",
endpoint: "dynamodb.ap-south-1.amazonaws.com"
});
var addDocumentToTable = function (tablename, item, callback) {
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: tablename,
Item: item
}
docClient.put(params, function (err, data) {
retData = { status: true, message: "Successfully inserted", error: null };
if (err) {
retData.status = false;
retData.message = "Failed to insert into DynamoDB";
retData.error = err;
}
callback(err, retData);
});
}
Adding the details to the DocumentClient has solved it.
var docClient = new AWS.DynamoDB.DocumentClient({ region: Config.AWS.AWS_REGION, endpoint: Config.AWS.ENDPOINT });

Unable to connect to dynammo db from Lambda

I have written a simple lambda function to list the tables on DynammoDb. But When i execute My code, I am unable to connect to the DB server . I am getting NetworkingError .
Below is the Code,
'use strict';
console.log('Loading function');
exports.handler = (event, context, callback) => {
console.log("$$$$$$$$$second test$$$$$$$$$$")
//var src_bkt = event.Records[0].s3.bucket.name;
//var src_key = event.Records[0].s3.object.key;
var AWS = require("aws-sdk");
//console.log(src_bkt)
console.log("##########################################")
console.log("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
var dynamodb = new AWS.DynamoDB({
region: 'us-east-1',
endpoint: "http://localhost:8000"
});
dynamodb.listTables({Limit: 10}, function(err, data) {
if (err) {
console.log("Error", err.code);
} else {
console.log("Table names are ", data.TableNames);
}
});
};
Any suggestion will be helpful
You need to create an instance of documentClient like below,
var docClient = new AWS.DynamoDB.DocumentClient();
And call 'listTables' with documentClient. Please find a sample code for PUT which shows how I am using documentClient,
var AWS = require("aws-sdk");
AWS.config.update({
region: "REGION"
});
var docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
var table = "EmployeeDetails";
var params = {
TableName: table,
Item: {
"Id" : event.Id,
"FirstName": event.FirstName,
"LastName": event.LastName,
"Age": event.Age,
"Gender": event.Gender
}
};
docClient.put(params, function (err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
callback(null, "Added item:", JSON.stringify(data, null, 2))
}
});
};
If you are running in Lambda region is not mandatory but it will work with region as well.
The same code is in my GitHub as well - https://github.com/vnathv/DynamoDb-CRUD.git

Resources