How to add key, value to Json data from mongoDB? - node.js

I stored product data in MongoDB and image in S3. So I'm trying to add img url to each of product data and send it together, but it doesn't work. I'm using node.js. Thanks
app.get("/products/getAllProducts", (req, res) => {
const path=[];
mongoose.model('Product').find().exec((err, productInfo) => {
if (err) return res.status(400).send(err);
productInfo.forEach(productInfo => {
s3.getSignedUrl(
"getObject",
{
Bucket: Bucket_NAME,
Key: productInfo.No+'.png'
},
(err, url) => {
if (err) {
throw err;
}
//console.log(url);
//path.push(url);
//path[productInfo.No] = url
productInfo.img = url;
//return productInfo;
}
);
})
res.status(200).json({ success: true, productInfo });
});
});

Related

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'unlink' of undefined at Grid.remove

I'm trying to delete a file by its id using gridfs but I get this error when calling the delete API.
Controller :
let gfs;
connect.once("open", () => {
gfs = Grid(connect.db, mongoose.mongo);
gfs.collection("uploads");
});
exports.deleteFile = (req, res) => {
try {
gfs.remove(
{ _id: req.params.id, root: "uploads" },
(err, gridStore) => {
if (err) {
return res.status(404).send({ message: err });
} else {
return res.send({ message: "File deleted successfuly" });
}
}
);
} catch (error) {
return res.status(500).send({
message: error.message,
});
}
};
exports.deleteFileByFilename = async (req, res, next) => {
const file = await gfs.files.findOne({ filename: req.params.filename });
const gsfb = new mongoose.mongo.GridFSBucket(conn.db, { bucketName: 'uploads' });
gsfb.delete(file._id, function (err, gridStore) {
if (err) return next(err);
res.status(200).end();
});
};
// #route DELETE /files/:filename
// #desc Delete file
app.delete('/files/:filename', async (req, res) => {
const file = await gfs.files.findOne({ filename: req.params.filename });
const gsfb = new mongoose.mongo.GridFSBucket(conn.db, { bucketName: 'uploads' });
gsfb.delete(file._id, function (err, gridStore) {
if (err) {
res.status(404).send('no file found')
}
res.status(200).send('deleted successfully')
});
});
On client side:
const delImage = async (fileName) => {
await axios.delete(`http://localhost:5000/files/${fileName}`);
console.log('fileDeleted');
getData(); // reminder to REFETCH the data so that database with deleted file is refreshed
}
I also made a video on this - full file uploads, multiupload, display and delete using MERN stack and NPM Multer thing, in here: https://youtu.be/4WT5nvfXcbs
Docs for the video with full code: https://docs.google.com/document/d/1MxvNNc9WdJT54TpanpFBT6o7WE_7hPAmDhdRNWE8A9k/edit?usp=sharing

export values from dynamoDB getItem

I'm trying to get data outside of the getItem function off the dynamoDB, but I'm getting this error and I don't know why.
Error ValidationException: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes
Here is my code
const aws = require("aws-sdk"),
docClient = new aws.DynamoDB.DocumentClient({ apiVersion: "2012-08-10" }),
ddb = new aws.DynamoDB({ apiVersion: "2012-08-10" }),
tableName = "usersDB",
exports.apiKey = async (req, res, context) => {
var params = {
TableName: tableName,
Key: {
"username": { "S": req.body.username },
},
ProjectionExpression: "apiKey"
};
chaveAPI = await ddb.getItem(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Item);
}
});
};
EDIT1: Fixed the validation error but still cannot get data from dyname. Here it is fixed
exports.apiKey = async (req, res) => {
console.log("comecei")
var params = {
TableName: tableName,
Key: {
'username': {S: req.user.username}
},
ProjectionExpression: 'apiKey'
};
// Call DynamoDB to read the item from the table
dataFromDynamo = await ddb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Item);
return data.Item
}
});
console.log(dataFromDynamo)
};
A few things I notice with your code sample:
You are mixing callbacks with async/await.
You aren't declaring the dataFromDynamo variable.
Instead of this
// Call DynamoDB to read the item from the table
dataFromDynamo = await ddb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Item);
return data.Item
}
});
Do this
try {
// Call DynamoDB to read the item from the table
const dataFromDynamo = await ddb.getItem(params).promise()
console.log("Success", data.Item);
return data.Item
} catch (err) {
console.log("Error", err);
}

How do I get the ID of the document I just inserted into MongoDB? (API)

I am trying to get the ID of the document that I just inserted into mongoDB. Here is the node.js code:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err) => {
if (err) {
res.status(500).send(err);
} else {
var id = dbGroup._id;
res.status(201).send(id);
}
});
});
I have tried various things, like adding a group to the function:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, group) => {
if (err) {
res.status(500).send(err);
} else {
var id = group._id;
res.status(201).send(id);
}
});
});
But that also does not work, so I tested if my even get the API response on the front end with:
res.status(201).send("test");
Which works perfectly fine. So I don't know why this doesn't work, because all the documentation says this is the way.
I figured a way to get the id. It may be not the most efficient way, because it sends all the data it gets but it gets the job done.
Backend:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(201).send(data);
}
});
});
Front end:
axios.post("/groups/new", {
groupname: roomName,
}).then((res) => {
roomid = res.data._id;
});

404 Not found when upload files nodejs

I am using multer package
I have two ways of uploading images to my server one is with Array and the other is using fields.
The only thing that works is the uploadArray for the /status route.. when i'm uploading to /update it gives me this error SyntaxError: Unexpected token < in JSON at position 0.. The controller for the /update is just the same as the postController.js the only difference it that i update fields instead of save new one.
/utils/lib/account.js
const storage = multer.memoryStorage();
// These two image might be available in the req.files depending on what was sent
const upload = multer({storage}).fields([{ name: 'photo', maxCount: 1 }, { name: 'cover', maxCount: 1 }]);
const uploadArray = multer({storage}).array('image', 12);
exports.upload = (req, res, next) => {
upload(req, res, function (err) {
if (err) {
console.log(err);
}
next();
});
};
exports.uploadArray = (req, res, next) => {
uploadArray(req, res, function (err) {
if(err){
console.log(err);
}
next();
});
};
/routes.js
router.route('/status')
.all(helper.verifyToken)
.all(helper.uploadArray)
.get(status.get)
.post(status.new) // file uploads
.delete(status.delete);
router.route('/update')
.all(helper.verifyToken)
.all(helper.upload)
.post(account.update_profile) // file uploads
The only thing that works here is the uploadArray
/postController.js
new:
(req, res) => {
const uri = new DataUri();
const promises = [];
const images = [];
//Get buffer from files
for(let key in req.files){
const obj = req.files[key];
uri.format('.png', obj.buffer);
let uriContent = uri.content;
promises.push(uploadAsync(uriContent)); //upload each image
}
//Init upload
function uploadAsync(buffer){
return new Promise((resolve, reject) => {
cloudinary.v2.uploader.upload(buffer, function(error, result) {
if(error){
reject(error);
}
if(result.url){
images.push(result.url);
resolve(images);
}
});
});
}
Promise.all(promises)
.then(results => {
// Init post model
console.log('test1')
const post = new Post({
post_img: images,
post_description: req.body.description,
post_by: req.body.id,
photoURL: req.body.id,
post_comments: []
});
// Save data
post.save(function(err) {
if(err) {
res.send(err);
}
var leanObject = post.toObject(); // Transform instance to plain JS Object for modification
// Modifications
leanObject['post_by'] = {
_id: leanObject['post_by'],
display_name: req.body.user, // Add current user display name
photo_url: req.body.user_photo
};
res.json({message: 'Success', type: 'success', code: 200, data: leanObject});
});
})
.catch(err => {
console.log(err);
});
},

Google storage bucket is public and still no access to files

I am creating a public bucket with nodeJS (apologise for the ES5/ES6 mix, copied Google's example were ES5):
var gcloud = require('google-cloud');
const gcs = gcloud.storage({
projectId: 'h-212f6',
keyFilename: './h-9a814129651f4.json'
});
const createBucket = (bucketName) => {
// Create a new bucket.
return new Promise((resolve, reject) => {
gcs.createBucket(bucketName, function (err, bucket) {
if (err) {
reject(err);
}
bucket.acl.add({
entity: 'allUsers',
role: gcloud.storage.acl.READER_ROLE
}, function(err, aclObject) {
console.log('err -> ', err);
});
resolve(bucket);
});
});
};
const upload = (bucket, filepath, options) => {
return new Promise((resolve, reject) => {
bucket.upload(filepath, options, function (err, file) {
if (err) {
reject(err);
}
resolve(file)
});
});
};
Yet having trouble accessing the file from Chrome:
UPDATE:
When I change the file's ACL all seems to work:
const upload = (bucket, filepath, options) => {
return new Promise((resolve, reject) => {
bucket.upload(filepath, options, function (err, file) {
if (err) {
reject(err);
}
file.acl.add({
entity: 'allUsers',
role: gcs.acl.READER_ROLE
}, function (err, aclObject) {
console.log('err -> ', err);
});
resolve(file)
});
});
};
However, I was under the assumption that changing the bucket ACL should be enough, isn't it?
When you set the ACL in your code above, you're setting it for existing objects. In order to set it as the default ACL for new objects, too, you need to do the following:
bucket.acl.default.add({
entity: 'allUsers',
role: gcloud.storage.acl.READER_ROLE
}, function(err, aclObject) {
console.log('err -> ', err);
});
See here for more examples.

Resources