AWS lambda function retrieving dynamodb data as a error message - node.js

I have written simple Lambda function to scan data from dynamodb, but data is getting retrieved with error message tag and lambda function shows message as execution failed
var AWS = require('aws-sdk');
var DOC = require("dynamodb-doc");
var dynamo = new DOC.DynamoDB();
exports.handler = function (event, context, callback) {
var params = {
TableName: "Movies",
// ProjectionExpression: "#yr, Movie",
FilterExpression: "#yr = :thisyear",
ExpressionAttributeNames: {
"#yr": "year",
},
ExpressionAttributeValues: {
":thisyear" : 2009
}
};
dynamo.scan(params, function(err, data){
if (err){
callback("error occoured");
}
else{
callback(JSON.stringify(data.Items));
}
});
};
Result
{
"errorMessage": "[{\"year\":2009,\"Movie\":\"Jab tak hai jaan\"}]"
}

nodejs callback are typically error-first callbacks. It means that the first parameter is the error message and the second parameter is the result. So when returning the result you need to pass null as the first argument.
eg: callback(null, JSON.stringify(data.Items));
Please refer this article

Related

Facing this error "ValidationException: The parameter cannot be converted to a numeric value: NaN"

I am trying to enter the data in AWS Dynamo DB through the AWS Lambda function using AWS HTTP API. FYI The data type of the parameter (Id) originally in Dynamo DB is Number but it is taking as String while parsing JSON data, so I have written "Number" beside "Id" parameter in order to convert it to "Number". When I am trying to run this lambda function I am getting this error. Please help, Thanks!
Lambda function:
payload: { "Id": $input.json('$.Id') "name": $input.json('$.name')
console.log('starting function');
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = function(event, ctx, callback) {
var params = {
Item: {
Id: Number(event.Id),
name: event.name
},
TableName: 'Test'
};
console.log(params)
docClient.put(params, function(err, data) {
if(err) {
callback(err, null);
} else{
callback(null, data);
}
});
}
Error log:
Look at the logs.
Your event.Id value is "NaN" which means "not a number".
Also event.name is "undefined".
So your problem is occuring here:
exports.handler = function(event, ctx, callback) {
Your event object is not populated with the values you are expecting.
The payload should be proper JSON and look something like:
{
"id": "6",
"name": "Test Name"
}
To achieve this, in your POST from your front-end code you could use something like:
data: JSON.stringify({"id": $('#Id').val(), "name": $('#name').val()})
Make sure that $('#Id').val() and $('#name').val() actually have proper values.

Can't scan DynamoDb with multiple where conditions using Node JS

AWS Documentation Sucks, I can't seem to get an idea of how to "scan" DynamoDb with two or more where conditions, in NodeJS ?
Here's my code
const AWS = require("aws-sdk");
let documentClient = new AWS.DynamoDB.DocumentClient();
module.exports.RetryIncompleteCSV = async (event, context, callback) => {
console.log('In RetryIncompleteCSV');
const cmpId = event.queryStringParameters.campaign;
console.log('cmpId = ', cmpId);
var params = {
TableName : 'processed_csv_developments',
FilterExpression : 'campaignId = :campaignId',
ExpressionAttributeValues : {':campaignId' : cmpId}
};
let incompleteCsvData = await scanIncompleteProcessedCsv(params);
console.log('incompleteCsvData = ', incompleteCsvData);
}
async function scanIncompleteProcessedCsv(params) { // get method fetch data from dynamodb
console.log(params)
const queryExecute = await documentClient.scan(params, function(err, data) {
if (err) console.log(err);
else console.log(data);
console.log('queryExecute=',queryExecute)
});
}
I need scan to filter out data, based on following two conditions:
campaignId must be equal to the campaignId that I get from query params.
isComplete should be equal to false (Boolean)
The code written above neither give any error nor a success message. Attaching the cloudwatch logs screenshot below :
What am I missing. I looked at a lot of questions and tutorials, but nothing worked for me. Please Help!
scanIncompleteProcessedCsv should return a promise. Now it returns void, this mean RetryIncompleteCSV function will finish before a querying to dynamoDB complete.
async function scanIncompleteProcessedCsv(params) { // get method fetch data from dynamodb
console.log(params)
return await documentClient.scan(params).promise();
}
About multiple conditions, I found to many documents about that, just try:
var params = {
TableName : 'processed_csv_developments',
FilterExpression : 'campaignId = :campaignId AND isComplete = false',
ExpressionAttributeValues : {':campaignId' : cmpId}
};
Ref: Link

How to call a Lambda function within a another Lambda function using Lex?

I am playing with AWS Lambda along with Twilio. I have a Lambda function that integrates Lex with Twilio. I also have another Lambda function that does the the validations for my LexBot. Both work fine separately. However, I'm trying to put them together so whenever my LexBot integrates with Twilio, it also calls my validations in the same Lambda function.
Any ideas? Thank you.
Here is the Lambda that integrates Lex with Twilio:
var twilio = require('twilio');
var qs = require('qs');
var AWS = require('aws-sdk');
exports.handler = (event, context, callback) => {
try {
var twilioSMS = qs.parse(event["body-json"]);
// ************************
// validate and filter bad/empty messages
// ************************
if(!twilioSMS.hasOwnProperty('Body')){
var error = new Error("Cannot process message without a Body.");
callback(error);
}
else {
// Message is valid so now we prepare to pass it along to the Lex API.
AWS.config.region = 'us-east-1';
var lexruntime = new AWS.LexRuntime();
var userNumber = twilioSMS.From.replace('+', '');
var params = {
botAlias: process.env.BOT_ALIAS,
botName: process.env.BOT_NAME,
inputText: twilioSMS.Body,
userId: userNumber,
sessionAttributes: {
}
};
lexruntime.postText(params, function(err, data) {
var twimlResponse = new twilio.TwimlResponse();
if (err) {
console.log(err, err.stack); // an error occurred
twimlResponse.message('Sorry, we ran into a problem at our end.');
callback(err, twimlResponse.toString());
} else {
console.log(data); // got something back from Amazon Lex
twimlResponse.message(data.message);
callback(null, twimlResponse.toString());
}
});
}
} catch(e) {
console.log(e);
callback(e);
}
};
And here is my Lambda with the validations:
exports.handler = (event, context, callback) => {
// TODO implement
var numberType =event.currentIntent.slots.number,
response = "is not valid. Try 'One' or 'Two'." ;
if(numberType === "one" ) {
response = "Call: 111 111 1111 "
}
else if(numberType === "two") {
response = "Call: 222 222 2222"
}
callback(null, {
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": "Your option: " + event.currentIntent.slots.number + ": " + response
}
}
});
};
Step functions would be your friend. Please have a look at below links,
https://aws.amazon.com/step-functions/
https://cloudacademy.com/blog/aws-step-functions-a-serverless-orchestrator/
I realized didn't need to write a Lambda function to connect Lex with Twilio. All I had to do was go to 'Channels' under my LexBot Console and integrate manually my bot with my Twilio account.

how to use node js to combine data from two jsons

I want to merge data from two tables and then send the result as the response.
I'm new to nodejs and lambda and I'm unable to figure out how I can merge json data from both scan calls and send it as the response.
If I uncomment the callback then response for only one table is sent.
My code is below, can someone please help in completing it
'use strict';
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event, ctx, callback) {
var params= {
TableName:'x',
FilterExpression:'SessionId = :SessionId',
ExpressionAttributeValues:{ ":SessionId" : 'ca47a131'},
};
var params1= {
TableName:'y',
FilterExpression:'sessionid = :SessionId',
ExpressionAttributeValues:{ ":SessionId" : 'ca47a131'},
};
docClient.scan(params, onScan);
docClient.scan(params1, onScan1);
function onScan(err, data){
if(err){
callback(err, null);
}else{
//callback(null, data);
}
}
function onScan1(err, data){
if(err){
callback(err, null);
}else{
//callback(null, data);
}
}
}
You can use the following modification to the code so that you can send the response in a single callback.
'use strict';
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function(event, ctx, callback) {
var params= {
TableName:'x',
FilterExpression:'SessionId = :SessionId',
ExpressionAttributeValues:{ ":SessionId" : 'ca47a131'},
};
var params1= {
TableName:'y',
FilterExpression:'sessionid = :SessionId',
ExpressionAttributeValues:{ ":SessionId" : 'ca47a131'},
};
docClient.scan(params, onScan);
docClient.scan(params1, onScan1);
var firstResultData = false;
function runAfterBothCallbacks(data){
if(!firstResultData){
firstResultData = data;
}else{
// Combine firstResultData with data and return in the callback
callback(null,{ dataX: firstResultData, dataY: data });
// Note: The order of scan and scan1 result coming cannot be guaranteed so, dataX can be the results of scan or scan1. If you can identify the result based on the scan, either pass it as another parameter to the runAfterBothCallbacks method or identify the scan based on data result (If possible).
}
}
function onScan(err, data){
if(err){
callback(err, null);
}else{
runAfterBothCallbacks(data);
}
}
function onScan1(err, data){
if(err){
callback(err, null);
}else{
runAfterBothCallbacks(data);
}
}
}
Welcome to JavaScript asynchronous callbacks (aka callback hell).
Fortunately, the AWS SDK supports promises so you can use Promise.all() to wait for multiple promises to be resolved. When that happens, merge the JSON results and return the merged result via the Lambda function's callback() method.

Trying to use AWS lambda to send data to a dynamodb table

console.log('starting function');
var dynamodb = new AWS.DynamoDB();
var AWS = require('aws-sdk');
exports.handler = function (e, ctx, callback) {
var params = {
Item: {
"Name": {
S: "Dalton Warden"
},
"PhoneNumber": {
S: "796-353-1416",
}
},
ReturnConsumedCapacity: "TOTAL",
TableName: "CustomerInfo"
};
dynamodb.putItem(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
};
I'm pretty new to lambda and dynamoDB but i'm trying to send data to a table I have set up. I've been through amazon's documentation and looked for similar instances on this site and The formatting looks like it would return the correct JSON but I'm still having trouble. The error I'm getting is Cannot read property 'DynamoDB' of undefined".
Please change the order of the below statements as mentioned below (first AWS and then dynamodb).
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB();

Resources