I'm trying to compare if dynambodb has duplicate phoneNumbers and if it does I want to delete the older one. There doesn't seem to be a whole lot, on doing this through lambda. Some help would be appreciated. Thanks
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: process.env.DYNAMODB_TABLE,
ProjectionExpression: "phoneNumber, createdAt",
};
module.exports.list = (event, context, callback) => {
// fetch all LakeSubscriptions from the database
dynamoDb.scan(params, (error, result) => {
// handle potential errors
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t fetch the item.',
});
return;
}
/*
for(item in result.phoneNumber){ //not really sure how I can pull these individual values I need to use to compare.
module.exports.delete = (event, context, callback) => {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: event.pathParameters.id,
},
};
// delete the lakeSubscription from the database
dynamoDb.delete(params, (error) => {
// handle potential errors
if (error) {
//error handling
});
return;
}
});
};
}
*/
// create a response
const response = {
statusCode: 200,
body: JSON.stringify(result.Items),
};
callback(null, response);
});
};
Not a expert in Node.JS , but some suggestions
Scan operation results are returned in pages of 1 MB each, So the above code will not return all the rows in the dynamodb . Refer to the Step 4.3: Scan of this documentation
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.04.html
This would give you some idea on how to paginate and get all records from dynamodb . you can add all the results
Also refer the following post
How to fetch/scan all items from `AWS dynamodb` using node.js
This should give u a better idea
Related
I am writing node js 10.x lambda function to put details into DynamoDB table.
Below is code
const AWS = require('aws-sdk');
var db = new AWS.DynamoDB.DocumentClient();
var tableName="xyz";
exports.handler = async (event) => {
// TODO implement
console.log("Event: "+ JSON.stringify(event));
var response = {
statusCode: 200,
"headers": {
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
},
};
await db.put({
TableName: tableName,
Item: {
userid: event.userid,
}
}, (error, data) => {
if (error) {
console.log("error:"+ error);
}
else{
console.log("Success");
}
}).promise();
return response;
};
I am getting kind on random number of success return
Output execution 1
2019-11-07T07:03:45.388Z f451dfc1-01ea-41d0-a998-945cb0f18be1 INFO Success
2019-11-07T07:03:45.510Z f451dfc1-01ea-41d0-a998-945cb0f18be1 INFO Success
2019-11-07T07:03:45.511Z f451dfc1-01ea-41d0-a998-945cb0f18be1 INFO Success
Output execution 2
2019-11-07T07:08:19.270Z 3ce51f5d-bbbc-4dd6-b46f-2149ee9bb9cf INFO Success
Output execution 3
2019-11-07T07:08:27.410Z 2625bba5-b8e1-40e4-8704-7c0d486f6dff INFO Success
2019-11-07T07:08:27.431Z 2625bba5-b8e1-40e4-8704-7c0d486f6dff INFO Success
**
does anyone know the cause of this problem?
I am relatively new to node js 10.x. so please help me if I have missed something in code
**
you are using a callback and promise at the same time, remove the callback.
You can try something like
exports.handler = async (event, context) => {
const params = {
TableName: tableName,
Item: {
userid: event.userid,
}
};
try {
const data = await dynamoDB.put(params).promise();
console.log("Data: ", data);
} catch(error) {
console.error("Error:", error);
}
}
I'm trying to put data into Dynamodb using serverless deployment. I have added the permission to write to Dynamodb.
The api is always sending {"message": "Internal server error"} but is able to put the data into db once if tried 5,6 times.
Following is the serverless.yaml config
handler: dynamoUpdate.handler
events:
- http:
path: /createdbentry
method: get
cors: true
Following is the code:
const AWS = require('aws-sdk')
AWS.config.update({ region: process.env.REGION || 'us-east-1' })
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = async (event) => {
return await createDBEntry("i123","Working");
}
const sendRes = (status, body) => {
var response = {
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: body
};
return response;
};
const createDBEntry = async function(id,result) {
var params = {
TableName: 'emplist',
Item: {
'ID' : {S:id},
'Summary':{S: result},
}
};
ddb.putItem(params, function(err, data) {
console.log("Here comes me.")
if (err) {
console.log("Opps Error");
return sendRes(403,err);
} else {
console.log("Complete")
return sendRes(200,data);
}
});
}
How can it be resolved ?
The problem is you are not returning any promise or awaiting anything async in your function called createDBEntry. Thus your handler returns undefined which makes apigateway return 500 internal server error.
You are mixing callbacks and async/await.
Your createDBEntry function should look like this.
const createDBEntry = async function(id, result) {
var params = {
TableName: 'emplist',
Item: {
'ID' : {S:id},
'Summary':{S: result},
}
};
try {
let data = await ddb.putItem(params).promise()
return sendRes(200, JSON.stringify(data))
} catch (err) {
console.log("Oops Error");
return sendRes(403, err.toString());
}
}
When you return from an async handler in lambda the current execution environment is frozen immediately (unlike when you use a non-async handler with a callback). This is why most of the time the writes to the database does not succeed.
I'm new to NodeJS and I'm supposed to write a serverless rest API for a online store (school project). The team I'm in is responsible of the orders customers place. To be able to place the order there has to be enough quantity in inventory (another API), so we need to check quantity in inventory using GET before we store the order in a database using POST. How should we go about this? This is what I have tried, but I end up getting timeout. The code below is based on this example: aws-node-rest-api-with-dynamodb for me to get the hang of NodeJS and serverless.
.yml file
functions:
create:
handler: todos/test.f
events:
- http:
path: todos
method: post
cors: true
test.js
const create = require("./create.js");
exports.f = function() {
const https = require('https');
https.get('url goes here', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(data);
var str = String(data);
console.log("Check: " + (str.trim() == "OK"))
create.c(); //also tried create.create();
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
create.js
'use strict';
const uuid = require('uuid');
const dynamodb = require('./dynamodb');
exports.c = function (){
console.log("Fire!");
}
module.exports.create = (event, context, callback) => {
const timestamp = new Date().getTime();
const data = JSON.parse(event.body);
if (typeof data.text !== 'string') {
console.error('Validation Failed');
callback(null, {
statusCode: 400,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t create the todo item.',
});
return;
}
const params = {
TableName: 'todos',
Item: {
id: uuid.v1(),
text: data.text,
checked: false,
createdAt: timestamp,
updatedAt: timestamp,
},
};
// write the todo to the database
dynamodb.put(params, (error) => {
// handle potential errors
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t create the todo item.',
});
return;
}
// create a response
const response = {
statusCode: 200,
body: JSON.stringify(params.Item),
};
callback(null, response);
});
};
Any thoughts on how to get this to work?
Is the uuid from context.awsRequestId really unique? I want to use it in association with the creation of a resource, so I can now when the resource was created:
const uuid = require('uuid');
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.create = (event, context, callback) => {
const timestamp = new Date().getTime();
const data = JSON.parse(event.body);
if (typeof data.text !== 'string') {
console.error('Validation Failed');
callback(null, {
statusCode: 400,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t create the todo item.',
});
return;
}
const params = {
TableName: process.env.DYNAMODB_TABLE,
Item: {
id: context.awsRequestId,
text: data.text,
checked: false,
createdAt: timestamp,
updatedAt: timestamp,
},
};
// write the todo to the database
dynamoDb.put(params, (error) => {
// handle potential errors
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'Couldn\'t create the todo item.',
});
return;
}
// create a response
const response = {
statusCode: 200,
body: JSON.stringify(params.Item),
};
callback(null, response);
});
};
Thank you.
I don't think this is clearly documented, but based on observations, these UUIDs do not appear to be randomly generated (which is good for uniqueness). Instead, they look like they are a variant of Type 1 UUIDs, where most of the bytes actually represent a timestamp, so it would appear to be a safe assumption that they are both spatially and temporally unique.
When the digit M in xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx is set to 1, the UUID should be a Type 1 and should represent a high resolution timestamp and "node" identifier, although in this case the node component seems to carry no meaningful information... but the timestamps seem close to real time (though not precisely so).
I have an array of items that I need to post to my server. I've tried the following but i never iterates.
var i = 0;
while (i < numOfItems) {
var item = items[i];
var a;
for(var ik in item){
console.log(item[ik]);
a = item[ik]; // Gets the key
break;
}
var formData = {
ID : ID,
UID : UID,
item : a
}
request.post({url:'http://example.com/a', formData: formData}, function(err, httpResponse, body){
if (err) {
return console.error('Post failed:', err);
}
console.log('Post successful! Server responded with:', body);
i++;
});
}
Your code won't work because request.post is asynchronous. If your objective is to make a call for each element in the array, a working and a more elegant solution would be to use Promises.all().
Here's your code modified with Promises —
function postRequest(url, formData) {
return new Promise((resolve, reject) => {
request.post({ url, formData }, function (err, httpResponse, body) {
if (!error) {
resolve({ message: 'Post successful!', response: body });
} else {
reject(err);
}
});
})
}
// Map your data array to an array of Promises
let promises = yourArray.map(element => {
let formData = {
ID: ID,
UID: UID,
item: element
}
return postRequest({ url: 'http://example.com/a', formData: formData })
});
// Wait for all Promises to complete
Promise.all(promises)
.then(results => {
// Handle results
})
.catch(e => {
// Handle error
});
A few things to note -
I'm reusing the fields ID and UID as-is, as it isn't clear where they come from in your code.
Replace yourArray with the array containing your data items.