Data not writing to subdocuments in MongoDB - node.js

I am using Node.js + Express for backend and MongoDB for database. My problem is that when I write data to the database, the subdocuments remain empty, i.e. I am not able to write data into the subdocuments.
Response
Fields employeeInformation up to cancellationReason are all subdocuments. When I do a console.log of req.body, I can see that my fields are populated with the correct values, but in MongoDB and in the response, there is no data. I can also write fine using Postman.
Here is my app.post code:
// POST
app.post('/create-incident', (req, res) => {
let incidentNumber = functions.createIncidentNumber();
let status = 'New';
const incidentHeader = new IncidentHeader({
incidentNumber: incidentNumber,
status: status,
employeeInformation: req.body.employeeInformation,
incidentDetail: req.body.incidentDetail,
spi: req.body.spi,
investigationDetail: req.body.investigationDetail,
recommendation: req.body.recommendation,
dataPrivacyDetail: req.body.dataPrivacyDetail,
infrastructureDetail: req.body.infrastructureDetail,
dataElement: req.body.dataElement,
processIncident: req.body.processIncident,
legislation: req.body.legislation,
dataPrivacyEducation: req.body.dataPrivacyEducation,
rca: req.body.rca,
approval: req.body.approval,
auditTrail: req.body.auditTrail,
cancellationReason: req.body.cancellationReason
});
console.log(`req.body: ${JSON.stringify(req.body)}`);
incidentHeader
.save()
.then(IncidentHeader => {
res.status(200).send(JSON.stringify(IncidentHeader));
console.log('Saved to IncidentHeader.');
})
.catch(e => {
return res.status(400).send(e);
console.log('Unable to save to IncidentHeader.');
});
});
What could I be doing wrong here?
Here is the link to my GitHub project should you wish to inspect the code further. Thank you in advance.
GitHub Repo

Related

how to read specific data from realtime database in node.js

I am working on API Get request. I have created a POST request to add the data in firebase realtime database. The code is as follows:
// CREATE POST
app.post("/post", (req, res) => {
let key;
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in.
var newPost = firebase.database().ref("posts/");
var myPost = newPost.push({
createdBy: user.uid,
from: req.body.from,
to: req.body.to,
duration: req.body.duration,
comments: req.body.comments,
});
res.send(newPost);
const postId = myPost.key;
console.log(postId);
} else {
// No user is signed in.
res.status(404).send("No user is signed in right now!");
}
});
});
Now, in order to get a specific post, I have written the following code:
// GET SPECIFIC POST
app.get("/post/:id", (req, res) => {
let response;
firebase
.database()
.ref("posts/" + req.params.id)
.on("value", (snapshot) => {
response = snapshot.val();
});
res.send(response);
});
I am new at Firebase, so I dont really know how to get a specific post. Please help me out
Calls to Firebase are asynchronous, because they require a call to the server. While that call is happening, your main code continues. And then when the data is available, your callback is invoked with the data from the server.
Right now your res.send(response) runs before the response = snapshot.val() is ever called. The rule with asynchronous APIs is simple: any code that needs the data needs to be inside the callback, or be called from there.
So in your case:
app.get("/post/:id", (req, res) => {
firebase
.database()
.ref("posts/" + req.params.id)
.once("value")
.then((snapshot) => {
res.send(snapshot.val());
});
});
You'll note that I also change from on to once, since you only care about getting the value once (instead of attaching a permanent listener that monitors the database for changes).
Dealing with asynchronous API is a common stumbling block, so I recommend spending some time reading these answers to learn more:
Why Does Firebase Lose Reference outside the once() Function?
Firebase response is too slow
Best way to retrieve Firebase data and return it, or an alternative way
I simply did this:
app.get("/post/:id", (req, res) => {
var key = req.params.id;
console.log(key);
firebase
.database()
.ref("posts")
.child(key)
.get()
.then((snapshot) => {
res.send(snapshot.val());
});
});
this solved the problem

Node JS Application not taking Values from postman

I wrote two node js applications, they are fetching data properly but they are not taking post values 1st applications is this TinderClone this is just an api with no frontend i am posting data from postman and it is returning auto generated id but not the data i am posting,
Other application i cloned from github, it has proper frontend with working CRUD, but when i tried to post values from postman it wont take any values it will just add record in database with null values, so is there anything wrong im doing on postman? cause it is still working if i post data with the form on its frontend the application url is MernCRUD
Postman Screenshots:
posting data,
fetching data
Code:
//Cards Schema (Cards.js)
import mongoose from 'mongoose'
const cardSchema = mongoose.Schema({
name: String,
imgUrl: String
})
export default mongoose.model('cards', cardSchema)
//Posting Data (Server.js)
app.post('/tinder/cards', (req, res) => {
const dbCard = req.body;
Cards.create(dbCard, (err, data) => {
if(err){
res.status(500).send(err)
}
else{
res.status(201).send(data)
}
})
})
//Fetching Data
app.get('/tinder/cards', (req, res) => {
Cards.find((err, data) => {
if(err){
res.status(500).send(error);
}
else{
res.status(200).send(data);
}
});
});
in postman you don't have to add content type manually . You should select json from the drop down and it will add content type by default. **
Now you have text in your raw dropdown change to json .
**

Client side can't fetch server response

The Problem
I deployed a create-react-app webapp to aws ec2. It's used to display data from a database and send data to it. I use ExpressJS, CORS and MySQL.
With the following code i fetch the corresponding URL and the server.js sends back the database content. Until here, everything works fine.
getBets = _ => {
fetch("http://ec2***.amazonaws.com
.then(response => response.json())
.then(response => this.setState({bets: response.data}))
.catch(err => console.error(err))
};
The problem begins when sending data to the database with the following code:
addBet = _ => {
const { bet } = this.state;
fetch(`http://ec2***.amazonaws.com/bets/add?name=${bet.person_name}&bet=${bet.time_bet}`)
.then(response => response.json())
.then(this.getBets)
.catch(err => console.error(err))
};
On click the addBet-function populates the db, but in chrome I following error:
GET http://ec2***.amazonaws.com/bets/add?name=Peter%20Pan5&bet=10:17%205 net::ERR_EMPTY_RESPONSE
and
TypeError: Failed to fetch
Regarding chrome dev-tools, the first error corresponds to the fetch in the addBet function and the second error to the catch part.
On the server side I've the following code for processing the fetch:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES("${name}", "${bet}", CURTIME())`;
connection.query(INSERT_BET, (err, res) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I want to mention, that the res paramter in the app.get part is unused. That tells me my IDE.
After a lot of hours digging deeper in the topics of expressJS and the fetch api, I guess, that the app.get part doesn't send a response to the server. But the fetch need some response.
My Question
How do I have to change the code in the app.get part to send a proper response back to the server?
AND
Am I right with my guess?
In MYSQL when you do an insert query you get back err,results and fields in the callback function like this:
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function (error,
results, fields) {
if (error) throw error;
console.log(results.insertId);
});
You have used the parameter res for result and then you have used res.send() which now corresponds to that res parameter in the callback function and not the res object.Rewrite it like this:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES(?,?,?)`;
connection.query(INSERT_BET,[name,bet,CURTIME()] ,(err, result) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I have also used prepared statement in place of normal sql queries. These are used to prevent sql injections. I hope it will work now.

What does this JSON response mean?

I am following a MEVN stack tutorial: https://appdividend.com/2018/11/21/mevn-stack-tutorial-with-example-from-scratch/#8_Setup_and_connect_MongoDB_database
In section 10 he shows how to create routes for adding, deleting, updating and reading data in a mongoDB database using mongoose.
This is part of that code:
// post.model.js
const express = require('express');
const postRoutes = express.Router();
// Require Post model in our routes module
let Post = require('./post.model');
// Defined store route
postRoutes.route('/add').post(function (req, res) {
let post = new Post(req.body);
post.save()
.then(() => {
res.status(200).json({'business': 'business in added successfully'});
})
.catch(() => {
res.status(400).send("unable to save to database");
});
});
Is there a specific reason he has put {'business': 'business in added successfully'} in the JSON for the 200 response? or can that just be anything? Also i'm not entirely sure what i would put in it for my specific scenario where i am trying to add, delete, update and read data about users in a 'users' collection.
It can be anything, just to information that received request is successful and created the records. He added some response to that request.

KeystoneJS CloudinaryImage upload via API

There seems to be lack of documentation on this topic. I'm trying to upload an image and set it to avatar: { type: Types.CloudinaryImage } in my Keystone model.
I'm posting content as multipart form data with the following structure: avatar: <raw_data>. Here is how I handle this in my API:
exports.upload_avatar = function(req, res) {
if (!req.files.avatar) {
console.info('Request body missing');
return res.status(400).json({ message: 'Request body missing', code: 20 });
}
req.current_user.avatar = req.files.avatar;
req.current_user.save();
}
where current_user is a mongoose model. What I find confusing is how to set my CloudinaryImage type field to the data I receive in the API.
So, rather than just setting the avatar to the raw data (which would work fine for e.g. a string field), you'll need to go through the update handler, which calls to the {path}_upload special path in cloudinary image.
You should then be able to do avatar.getUpdateHandler, perhaps following this example.
I would like to share what worked for me. The process is kind of strange but by adding in this code, all of the model validation works just fine and cloudinary uploads are set.
post(req, res, next) {
const newBundle = new Bundle(); //A mongoose model
newBundle.getUpdateHandler(req).process(req.body, (err) => {
if (err) {
return res.status(500).json({
error: err.message,
});
}
return res.json(newBundle);
});
}
When posting to the endpoint, all you need to do is make sure you set your file fields to be {databaseFieldName}_upload.
Ok after some digging through the source code, I figured out a way to do that:
exports.upload_avatar = function(req, res) {
req.current_user.getUpdateHandler(req).process(req.files, {fields: 'avatar'}, function(err) {
if (err) {
return res.status(500).json({ message: err.message || '', code: 10 });
}
res.send('');
});
}
I had the following gotchas:
use getUpdateHandler to update CloudinaryImage field.
use "magic" naming for multipart form data fields you POST to your API: {field_name}_upload, which in my case would be avatar_upload.
process req.files, which is a dictionary with your field names as keys and your file data as values. req.body is empty due to some post-processing with multer.
invoke update handler on your keystone model (you need to fetch it with find first) rather than on a specific field. Then specify {fields: <>} to limit its scope, otherwise you could have some issues like validation errors trying to update the whole object.

Resources