Trouble making a Query of DynamoDB with Lambda (Node.js) - amazon-web-services

I want to make a query to return all entries with a certain userID, in this case Will666. I have a primaryKey and a sortKey.
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB({region: 'eu-west-2', apiVersion: '2012-08-10'});
exports.handler = (event, context, callback) => {
const params = {
TableName: "signalepisodes",
KeyConditionExpression: "userID = :a",
ExpressionAttributeValues: {
":a": "Will666"
}
};
dynamodb.query(params, function(err, data){
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
const items = data.Items.map(
(dataField) => {
return { userID: dataField.userID.S, uploadDate: dataField.uploadDate.N, epTitle: dataField.epTitle.S };
}
);
callback(null, items);
}
});
};
i get this error message when i test it. I guess my syntax is wrong but i can't work it out.
"errorType": "MultipleValidationErrors",
my dynamoDB table looks like this:

The DynamoDB SDK has two types of client:
low-level client: new AWS.DynamoDB(...)
high-level client: new AWS.DynamoDB.DocumentClient(...)
You are currently using #1, but you are supplying attributes to your query as if you were using the document client #2.
So, either switch to the DocumentClient, and continue to use:
{":a": "Will666"}
Or stick with the low-level client and change your attributes to indicate value types, for example:
{":a": {"S": "Will666"}}
I'd recommend the DocumentClient because it significantly simplifies the marshalling and unmarshalling of data.
I would also recommend updating your code from the old callback style asynchronous code to the newer Promise-based options. For example, something like this:
exports.handler = async (event, context) => {
const params = {
TableName: "signalepisodes",
KeyConditionExpression: "userID = :a",
ExpressionAttributeValues: { ":a": "Will666" }
};
const items = await dynamodb.query(params).promise();
for (const item of items) {
console.log('Item:', item);
}
return items;
}

Related

How to put an item on DynamoDB table using AWS SDK for Node.js?

I have a DynamoDB table named MYTABLE
I'm trying to insert some data into this table via LambdaEdge.
My Lambda function is triggered via a CloudFront Distribution.
I have this function :
var AWS = require("aws-sdk");
AWS.config.update({region: 'us-east-1'});
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = async (event, context) => {
var params = {
TableName: 'MYTABLE',
Item: {
'id' : {'S': 'something'},
'value' : {'S': 'something'}
}
};
// Call DynamoDB to add the item to the table
await ddb.putItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
const response = {
status: '302',
statusDescription: 'Found',
headers: {
location: [{
key: 'Location',
value: 'https://www.google.com',
}],
},
};
return response;
};
The function runs properly (the redirection works) but no data is inserted into the table.
Does anyone know what I'm doing wrong please ?
Thanks.
Cheers,

How to scan the dynamodb table form the AWS Lambda function

I am trying to scan the Dynamodb table form my following code, can anyone please guide me what is wrong here.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB({
region: "eu-west-1",
apiVersion: "2012-08-10"
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
dynamodb.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
I have given full dynamodb access role to the function but still it gives me the null response. Any idea what can be wrong here?
Response:
I tried with dynaomClient which not working too.
const AWS = require("aws-sdk");
const db = new AWS.DynamoDB.DocumentClient({
region : 'eu-west-1'
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
db.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
Your Lambda function is async but your code uses callbacks. By the time the callback is reached, your function has already been terminated because it ran asynchronously. I'd speculate that the null output you see is the return value from the Lambda function, not your console.log.
Replace your call to scan with the following:
try{
let results = await db.scan(params).promise()
console.log(results);
} catch(err){
console.log(err)
}
For more info, check out the AWS documentation about working with promises.

Is there a way to get the input Transcript from LEX into a lambda which then allows connect to grab that transcript and set it as a contact attribute?

I have this lambda below that gets items from DynamoDB and returns it to connect just fine... however, I cannot seem to get the inputTranscript over. Is there a way I could implement this in my current lambda so that Connect can access it? I am seriously stumped on this, as everything I have tried in the documentation has not worked for me.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
exports.handler = function(event, context, callback) {
console.log(`DEBUG:\t Event`, JSON.stringify(event, null, 4));
var params = {
Key: {
"name": {
"S": '"' + event.slots.list + '"'
}
},
TableName: 'ServiceOfferings'
};
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log("ERROR:\t", err);
callback(err);
} else {
console.log(data);
if (data.Item) {
console.log('data returned from DynamoDB ', JSON.stringify(data));
callback(null, {
ServiceOffering: data.Item.name.S.slice(1, -1)
});
}
else {
console.log("no callback number found for intent");
callback(new Error("no callback number found for intent"));
}
}
});
};
The test instance I use to ensure the lambda works correctly is as follows:
{
"dialog-state": "ReadyForFulfillment",
"input-transcript": "my printer is not working",
"slots": {
"list": "Re-IP Project - Printers"
},
"intent-name": "getServiceOffering"
}
The response after Testing this comes out to:
{
"ServiceOffering": "Re-IP Project - Printers"
}
When you log the event, you should be able to see the inputTranscript being passed to your Lambda. So you simply need to take it out of the event and do with it what you want.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
exports.handler = function(event, context, callback) {
console.log(`DEBUG:\t Event`, JSON.stringify(event, null, 4));
var inputTranscript = event.inputTranscript
...
callback(null, {
ServiceOffering: data.Item.name.S.slice(1, -1),
inputTranscript: inputTranscript
});
That includes the inputTranscript in your callback to Connect (I assume), and you can use the Set Attribute block to save and handle the input within Connect.

DynamoDB : Query always returning null

I am quite new on DynamoDB, I just create a table where I inserted some dummy rows just to test the read / write functions.
Here is my data.
I create a Lambda to access these data, via Partition Key ok Sort Key but I ended up with a null return every time :'(
Here is the code of my lambda :
const dynamodb = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10', region: 'eu-west-1'});
exports.handler = async (event,context,callback) => {
var params = {
TableName : "DontMissAPlaceTable",
KeyConditionExpression: "Partition_Key = :id",
ExpressionAttributeValues: {
":id": {"S" : "media_001"}
}
};
dynamodb.query(params, function(err, data) {
if (err) {
console.log(err, err.stack);
callback(null, {
statusCode: '500',
body: err
});
} else {
console.log(data)
callback(null, {
statusCode: '200',
body: data
});
}
})
};
I first thought it was lack of access to the table but it seems I have the right permissions.
I am quite sure it's a dummy problem but i can't figure it out ...
Thanks for help :D
Your Lambda function is async but your code uses callbacks. By the time the callback is reached, your function has already been terminated because it ran asychronously.
Rather than using the outdated, confusing callback approach, just stick with async/await. The AWS SDK for Node.js already provides a .promise() method which you can call on asynchronous methods that use a callback, making it seamless to await on them.
That said, change your code to:
const dynamodb = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10', region: 'eu-west-1'});
exports.handler = async (event) => {
const params = {
TableName : "DontMissAPlaceTable",
KeyConditionExpression: "Partition_Key = :id",
ExpressionAttributeValues: {
":id": "media_001"
}
};
return {
statusCode: 200,
body: JSON.stringify(await dynamodb.query(params).promise())
}
};
Since you are already using the DocumentClient API, you don't need to specify the types ("S", "N", etc) when querying.
Also, make sure that Partition_Key really is your partition key. You use the name you defined in your table, no HashKey nor PartitionKey, meaning if you called your Hash Key id, then id should be used.

DynamoDB query using AWS Lambda

I am trying to select an entry from my database with id "1" (primary key) I am not sure what I am doing wrong, I also tried .getItem() method however with no positive result.
'use strict';
var AWS = require('aws-sdk'),
documentClient = new AWS.DynamoDB.DocumentClient();
exports.selectStatus = function(event, context, callback){
documentClient.query({TableName : "users", Key:{"id":"1"}}, function(err, data){
if(err){
callback(err, null);
}else{
callback(null, data.Items);
}
});
}
I am trying to build serverless REST API using AWS lambda, .scan() works perfectly but I want to filter the data. I have 2 values for each user in database, id(primary key(string)) and status (string).
FIXED UPDATE:
'use strict';
var AWS = require('aws-sdk'),
documentClient = new AWS.DynamoDB.DocumentClient();
exports.selectStatus = function(event, context, callback){
var params = {
TableName : "users",
KeyConditionExpression: "id = :id",
ExpressionAttributeValues: {
":id": "1"
}
};
documentClient.query(params, function(err, data){
if(err){
callback(err, null);
}else{
callback(null, data.Items);
}
});
}