Query DynamoDB to check if a particular item exists or not - node.js

I just started out with Node.js and AWS DynamoDB and I am stuck with a very basic problem. I would like to query my DynamoDB which has a "Users" table with "Username"(PKey) and "JoinedOn" columns. Now I would like to write a Lambda function to check if a particular Username exists or not and return a response on the basis of that. Currently I am using the below code:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
const params = {
TableName : 'Users',
Key: {
Username: 'user1'
}
}
async function getItem(){
try {
const data = await docClient.get(params).promise()
return data
} catch (err) {
return err
}
}
exports.handler = async (event, context) => {
try {
const data = await getItem()
return { body: JSON.stringify(data) }
} catch (err) {
return { error: err }
}
}
I am currently hardcoding the key (Username: 'user1') in my code, but I want to avoid doing that as I want to use the same code to check for different users, whether the Username exists in the "Users" table or not.
I want to use SAM. My event.json should look like below, as I want to check if user1 exists in "Users" or not:
{
"Username": "user1"
}
On running "sam local invoke TestFunction -e events/event.json", I should get a response "User exists" or "User does not exist"
I am new to AWS and development. Any help is really appreciated.
Thank you in advance!

you need to define that username in environment variable section of lambda.
then inside the lambda code you can simply call process.env.username.

Related

AWS SAM and DynamoDB Local

I want to create a API endpoint in Node.js that lists the table names in DynamoDB. I have created a simple table locally and confirmed the table exists with the command
aws dynamodb list-tables --endpoint-url http://host.docker.internal:8000
{
"TableNames": [
"SampleTable"
]
}
but my lambda returns
{"TableNames":[]}
here's my lambda
const AWS = require('aws-sdk');
const options = {
apiVersion: '2012-08-10',
region: 'us-east-1',
};
if (process.env.AWS_SAM_LOCAL) {
options.endpoint = new AWS.Endpoint('http://host.docker.internal:8000');
}
const ddb = new AWS.DynamoDB(options);
exports.listTablesHandler = async (event) => {
if (event.httpMethod !== 'GET') {
throw new Error(`listTables only accept GET method, you tried: ${event.httpMethod}`);
}
console.info('received:', event);
const params = {};
let response = { statusCode: '500' };
try {
response = await ddb.listTables(params).promise();
} catch (err) {
console.log(err);
}
return response;
};
I expected the Lambda to list the name "SampleTable" in the API response
You should check if you are using -sharedDb ?
If you use the -sharedDb option, DynamoDB creates a single database file named shared-local-instance.db. Every program that connects to DynamoDB accesses this file. If you delete the file, you lose any data that you have stored in it.
If you omit -sharedDb, the database file is named myaccesskeyid_region.db, with the AWS access key ID and AWS Region as they appear in your application configuration. If you delete the file, you lose any data that you have stored in it.

function exits when passing data to aws cognito after reading file from s3 in aws lambda in nodejs

i am new to this , i am having problem , i have to create almost 200 users in cognito after reading data from csv file which is located in S3 bucket
the problem is , if a user already exists in Cognito , my code stop executing and give me an error "An account with the given email already exists." is there a way that i can pass the whole data. if there is user already in the cognito with the same email, it skips that user and checks for the new user data , and at the end which users are already exists in cognito .this the function to create user in cognito
here is the function for creating the cognito user
function RegisterUser(data2) {
console.log(data2[1])
for(let i=0;i<=data2.length;i++){
var attributeList = [];
var cognitoUser;
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({ Name: "name", Value: data2[i][0]}));
attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({ Name: "email", Value: data2[i][1] }));
try{
return new Promise((resolve, reject) => {
userPool.signUp(data2[i][1], data2[i][2], attributeList, null, (err, result) => {
if (err) {
console.log(err.message);
reject(err);
return;
}
cognitoUser = result.user;
resolve(cognitoUser);
});
});
}catch(err){
return{
success:false,
message:err
}
}
}
}
here is the lambda handler
exports.handler = async (event, context) => {
try {
// Converted it to async/await syntax just to simplify.
const data = await S3.getObject({Bucket: 'user-data-file', Key: 'SampleCSVFile_2kb.csv'}).promise();
var data1 = Buffer.from(data.Body).toString();
var data2 = data1.split("\r\n"); // SPLIT ROWS
for (let i in data2) { // SPLIT COLUMNS
data2[i] = data2[i].split(",");
}
const userPoolResponse = await RegisterUser(data2);
}
catch (err) {
return {
statusCode: err.statusCode || 400,
body: err.message || JSON.stringify(err.message)
}
}
}
A quick google search brought this up: How to check Email Already exists in AWS Cognito?
Which sure thats Front end but your use case seem to be a quick once in a while run script, not a regular use User System - in which case, this is basic programing 101 to solve. You put another try catch around your call to register the user. You check the exception thrown, and if its 'already registered' you pass and continue in the loop without interruption. The above link can give you some idea of what to look for to determine if it is that exception or not.

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.

DynamoDB getItem returns empty item

I am using the aws-sdk within Node and trying to get an item from a DynamoDB table but it prints just Success {} and not the actual content of the item. Does anyone know how to get the actual content of the item?
The Node script I am using is the following:
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'ap-southeast-2'});
// Create the DynamoDB service object
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
var params = {
TableName: 'test_table',
Key: {
'TWEET_KEY' : {S: 'Test'}
},
ProjectionExpression: 'ATTRIBUTE_NAME'
};
// Call DynamoDB to read the item from the table
ddb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Item);
}
});
and the actual data within the DynamoDB test_table which I'm trying to get is as follows:
Thank you very much!
Here - ProjectionExpression: 'ATTRIBUTE_NAME', you need to set the attribute names that you need to get, or just remove it to get the whole record content.

How do I use batchWriteItem with Node.js to query AWS DynamoDB?

I'm new to AWS and I'm having problems trying to develop a simple Lambda function with Node.js. In DynamoDB, I have a table named Game with 3 attributes: gamepk, user, result.
In just one single execution of the Lambda function, I want to insert a collection of game elements (the number of elements in the collection could vary).
I had been reading some tutorials and it said I should use batchWriteItem, but because the collection of Game elements is variable I don't know how to proceed.
Could somebody write a function in Node.js that solves my problem?
An example of the JSON that the lambda function receives is this one:
{
"games": [{
"gamepk": "1",
"user": "rolo",
"result": "1-0"
},
{
"gamepk": "2",
"user": "jhon",
"result": "1-1"
}
]
}
This should get you what you need.
Create a New Lambda Function
Select Node Version 6
Select a Role or Create a New one that has DynamoDB Access to Write!
Open Created Function in the Web Console
Paste the Snippet Bellow into the Cloud 9 Editor
const AWS = require('aws-sdk/global');
exports.handler = (event, context, callback) => {
// The event parameter is the input to your lambda function
console.log(JSON.stringify(event));
let lambdaInput = event['PROPERTY_NAME_DEFINED_IN_POST'];
let games = [];
let documentClient = new AWS.DynamoDB.DocumentClient();
lambda.forEach(item => {
games.push({
PutRequest: {
Item: {
gamepk: item['gamepk'],
user: item['user'],
result: item['result']
}
}
});
});
let params = {
RequestItems: {
'TABLE_NAME': games
}
};
documentClient.batchWrite(params, function(err, data) {
if (err) {
callback(err);
} else {
callback(null, data);
}
});
}
Save the Function and then you are going to want to select the drop down at the top that says 'Select a Test Event' and then select 'Configure Test Events'.
This will open a new dialog, just save the JSON that is in the main text area and give the test a Name and Save it.
Now select that test that you just made from the 'Select a Test Event' drop down and then click 'Test' in the top right.
This documentation could be found at AWS Javascript SDK
As an additional help for the answer , you can use an environment variable and use it in the following way:
const MI_TABLE = process.env.MI_TABLE
let params = {
RequestItems: {
[ MI_TABLE ] : games
}
};
return await batchWrite(params);

Resources