Calling a mysql column using template literals node js - javascript

I am trying to call a field from mysql within my node js file using template literals but am unable to obtain the value. Please take a look at my post.controller.js file below where is says message: Post ${body.post_id} was successfully created where post_id is a field within my mysql database.
//The following code is in post.service.js file
const pool = require("../../config/database");
module.exports = {
//Create new post
createPost: (data, callBack) =>{
pool.query(
`insert into posts(userhandle, post_body)
values(?,?)`,
[
data.userhandle,
data.post_body
],
(error, results, fields) =>{
if(error){
return callBack(error);
}
return callBack(null, results);
}
);
}
}
//The following code is in post.controller.js file
const {
createPost,
} = require("./post.service");
module.exports = {
//Controller for creating new post
createPost: (req, res) =>{
const body = req.body;
createPost(body, (err, results) => {
if(err){
console.log(err);
return res.status(500).json({
success:0,
message:"Error. Unable to create post"
});
}
return res.status(200).json({
success: 1,
message: `Post ${body.post_id} was successfully created`,
data: results
});
});
}
}

I'm guessing post_id is a PK auto incremented, if that so try results.post_id, since this is an object retuned from callback.
If this won't work do the console.log(results) and see if post_id is in it.

Related

Express/Postgres User registration controller

To simplify the situation I'll just post the following controller for an express route which interactions with a Postgres Database. My question is about error handling. If an error occurs it will be caught within the catch clause. But how can I access the errors thrown by the database queries itself. If I make several await several queries and one of them fails I need probably to restore stuff in the database? For example if the insertion of the user in the user table is a success, but the following query of inserting the user in another table fails, I need to delete the user from the user table again. How does one model such flows?
//
// Register User
//
export const registerUser = async (request, response, next) => {
try {
const usersWithSameMail = await client.query(`SELECT * FROM public.users WHERE email = '${user.email}'`);
if(usersWithSameMail.rows.length > 0){
return response.status(403).json({"code": "ERROR", "message": "Email is already registered"})
} else {
await client.query(`
INSERT INTO public.users(first_name, last_name, email, password)
VALUES ('${user.first_name}', '${user.last_name}', '${user.email}', crypt('${user.password}', gen_salt('bf', 8)));
`);
// more await statements...
return response.status(200).json({"code": "INFO", "message": "Verification mail sent to user"});
}
} catch (error) {
return response.status(500).json({"code": "ERROR", "message": "Error occured while registering the user. Please try again."});
}
}```
You can use middlewares chaining your routes handler. In order to it work, you will have to change your current working code to use Single-responsibility principle. Do only one responsability per middleware and chain all handlers to work as one.
Lets say you want to insert new user, to perform this operation we should:
lookup if email is unique
hash password
Insert new user
return inserted data in postgres back as a response
Following the middleware chaining we should implement a function for each action and chain each action in route definition:
const postgres = require('../../lib/postgres');
const crypto = require('crypto');
exports.insertedData = (req, res) => {
res.status(200).json(req.employee);
};
exports.hashPassword = (req, res, next) => {
crypto.scrypt(req.body.password.toString(), 'salt', 256, (err, derivedKey) => {
if (err) {
return res.status(500).json({ errors: [{ location: req.path, msg: 'Could not hash password'}] });
}
req.body.kdfResult = derivedKey.toString('hex');
next();
});
};
exports.lookupEmailUnique = (req, res, next) => {
const sql = 'SELECT e.email FROM public.users e WHERE e.email=$1';
postgres.query(sql, [req.body.email], (err, result) => {
if (err) {
return res.status(500).json({ errors: [{ location: req.path, msg: 'Could not query database' }] });
}
if (result.rows.length > 0) {
return response.status(403).json({"code": "ERROR", "message": "Email is already registered"})
}
next()
});
}
exports.insertNewUser = (req, res, next) => {
const sql = 'INSERT INTO public.users(first_name, last_name, email, password) VALUES ($1,$2,$3,$4} RETURNING *';
postgres.query(sql, [req.body.first_name, req.body.last_name, req.body.email, req.body.kdfResult], (err, result) => {
if (err) {
return res.status(500).json({ errors: [{ location: req.path, msg: 'Could not query database'}] });
}
req.employee = result.rows[0];
next();
});
};
here is your route declaration:
const router = require('express').Router();
const userService = require('../controllers/user.controller');
router.post('/register', userService.lookupEmailUnique, userService.hashPassword, userService.insertNewUser, userService.insertedData);
module.exports = router;
Here in routes you are using the middeware to do the chaning, you only pass the control to next middleware if all conditions are met and has full control from database erros.
In my example I do not used the async/await but I can change my example to have a version using async/await.
example middleware with transaction
exports.deletePostagem = async (req, res, next) => {
try {
await postgres.query('BEGIN');
const sql2 = 'UPDATE comentario SET postagem = null WHERE postagem = $1';
await postgres.query(sql2, [req.params.id]);
const sql3 = 'DELETE FROM postagem WHERE id = $1';
await postgres.query(sql3, [req.params.id]);
await postgres.query('COMMIT');
res.status(204).json();
res.end();
} catch (err) {
await postgres.query('ROLLBACK');
return res.status(500).json({ errors: [{msg: 'Could not perform operation' }]})
}
}
I used this only as an example, but in my projects I always have a middeware for validate/sanitize the data that comes in request before using in database query prepared statements.
based on transaction documentation in node.js you can use rollback
export const registerUser = async (request, response, next) => {
try {
let error = null;
const client; // create a client, connect to the db
try {
await client.query("begin");
await client.query("first query");
await client.query("second query");
await client.query("third query");
await client.query("commit"); //do commit when is finished all queries
} catch (error) {
error = error;
await client.query("rollback");
} finally {
client.release(); // close the connection
}
if (error) {
return response.status(500).json({ message: error }); // error message
}
return response.status(200).json({ message: "My message" }); // success message
} catch (err) {
return response.status(500).json({ message: err });
}
}

res.json not returning response

My res.json in my first block of code works, but in the else part of my if statement, it does not. The block that doesnt work, checks for a record in a database then im trying to return the response but im not receiving it.
I've checked and the response is a string, I thought it would have worked as the top part of the code successfully returns the string and it shows in dialogflow (where im trying to return it)
The response is successfully consoled right before the res.json but I do not receive it from the source of the request.
code:
app.post('/webhook/orderinfo', (req, res) => {
const intent = req.body.queryResult.intent.displayName;
const domain = "chatbotdemo.myshopify.com";
const order = req.body.queryResult.parameters["number-sequence"];
if (intent.includes('Order Number')) {
url = "https://test-hchat.com/api/orders/" + domain + "/" + order;
request(url)
.then(function (response) {
order_res = JSON.parse(response)
order_res["fullfillmentText"] = "Hi, Please find your order details below:";
res.json({
"fulfillmentText": JSON.stringify(order_res)
})
})
.catch(function (err) {
console.log(err)
});
// THIS PART DOESNT RETURN THE RESPONSE.
} else {
const domain = 'testStore'
db.getClientsDialog(domain, intent, (response) => {
const fullResponse = response.response
res.json({
fullResponse
})
})
}
});
The database code:
getClientsDialog: function (domain, intent, callback) {
MongoClient.connect('mongodb://efwefewf#wefwef.mlab.com:15799/wefwef', function (err, client) {
if (err) throw err;
var db = client.db('asdsad');
db.collection('dialog').findOne({ domain: domain, intent: intent }, function (err, doc) {
if (!err) {
callback(doc)
} else {
throw err;
callback(err)
}
client.close();
});
console.dir("Called findOne");
});
}
Could it be because this second use of the res.json in the else statement, is trying to call the db first and therefore the link is lost to send the data back?

ExpressJS variable undefined

I have an ExpressJS app that when a user makes a POST request to a route, it should lookup the ID in the MongoDB using req.params.formId
I have some console.log statements tfor debugging and so I can see what info is being returned.
The route should lookup the ID passed and when it finds it, use the req.body data and also a field from the MongoDB document but this just seems to return as undefined
Here is the code for the route:
app.post("/api/v1/forms/:formId", (req, res) => {
const { name, email, message } = req.body;
console.log(req.body);
Form.findById(req.params.formId, Form.recipient, err => {
if (err) {
res.send(err);
} else {
const formRecipient = Form.recipient;
const newForm = {
name,
email,
message,
recipient: formRecipient
};
console.log(newForm);
const mailer = new Mailer(newForm, contactFormTemplate(newForm));
try {
mailer.send();
res.send(req.body);
} catch (err) {
res.send(err);
}
}
});
});
So an example, if I make a POST request to localhost:5000/api/v1/forms/5ad90544883a6e34ec738c19 the console.log of newForm shows { name: ' Mr Tester',
email: 'person#example.com',
message: 'Hi there',
recipient: undefined }
The forms Mongoose schema has a field named recipient
the correct way is to provide the fields you want to get as the second argument:
Form.findById(req.params.formId, 'recipient', (err, form) => {
if (err) {
// error handling code
} else {
const formRecipient = form.recipient;
}
...
});
here's the Docs

Having issues editing an existing DB entry with Sails and Waterline

I'm using SailsJS as an API with Waterline connected to a MongoDB. I'm trying to put together an endpoint to edit existing DB entries but can't seem to get it to work and I'm hitting a wall as to why.
My route:
'post /edit/safety/:id': {
controller: 'SafetyController',
action: 'editSafety'
},
My controller function:
editSafety: function editSafety(req, res) {
var id = req.params.id;
Safety.findOneById(id).then((err, safety) => {
if (err) {
res.send(500, err);
return;
}
if (!safety) {
res.send(404, err);
return;
}
safety.title = req.body.title;
safety.description = req.body.description;
safety.status = req.body.status;
safety.save((err, updatedSafety) => {
if (err) {
re.send(500, err);
return;
}
res.send(200, updatedSafety);
});
});
},
Any push in the right direction would be greatly appreciated.
I don't recognize the Safety.findOneById method - is this something you have custom built? If not, then it is likely your problem.
Try swapping it for either:
Safety.findOne(id)
or
Safety.findOne({id: id})
Note that the returned object will be a model instance if the record exists, and undefined otherwise. If you decide to go with Safety.find instead then the returned value will be an array containing all models matching the query.
Looks like the main issue was transposing the response and err objects. It was successfully completing the query, but loading it into the err object which gets caught and a 500 error is thrown. So I changed that and simplified in a few other places.
editSafety: function editSafety(req, res) {
var id = req.params.id;
Safety.findOne(id).then((response, err) => {
var safety = response;
if (err) {
res.send(500, err);
return;
}
if (!response) {
res.send(404, err);
return;
}
safety.title = req.body.title;
safety.description = req.body.description;
safety.status = req.body.status;
Safety.update({
id: id
}, safety)
.then((result) => {
res.json(200, 'Ok!');
})
.catch((err) => {
sails.log.error('SafetyController.editSafety', err);
})
});
},

Node JS Multiple Select

Hi i am trying to use two selects in one JS file in node js and sql server. I am unable to figure out the syntax for this. I need a select to get all the persons from a table and another select to count the total number of persons in that table.Will it be possible to put those two selects in a single JS file. If so can someone help me with the syntax?
Here is the code i tried and i am getting the error
"cant Set headers after they are sent"
var sql = require("mssql");
var dbConfig = {
server: "XXXXX",
database: "XXXXX",
user: "XXXXX",
password: "XXXX",
port: 1433
};
exports.list = function(req, res){
sql.connect(dbConfig, function (err) {
if (err) console.log(err);
var request = new sql.Request();
request.query('select * from PERSON', function (err, recordset) {
if (err)
console.log(err)
else
console.log(recordset)
res.render('personinfo_itwx', { data: recordset });
});
request.query('select count(*) from PERSON', function (err, recordset) {
if (err)
console.log(err)
else
console.log(recordset1)
res.render('personinfo_itwx', { data: recordset1 });
});
});
};
#Aditya I'm not sure it's the best way to do so, although I would simply make two different requests, in order to achieve what you need. As I mentioned my in my comment, easiest way, would be to use (for instance) async library. And here's example you've asked for.
WARNING: I did not look at mysql docs
const async = require('async')
// {
async.series([
function(next)
{
new sql.Request()
.query('SELECT * from PERSON', next(err, resultList))
},
function(next)
{
new sql.Request()
.query('SELECT COUNT(*) from PERSON', next(err, count))
}
], (err, result) =>
{
/*
err: String
- if any of the shown above return an error - whole chain will be canceled.
result: Array
- if both requests will be succesfull - you'll end up with an array of results
---
Now you can render both results to your template at once
*/
})
// }
Surely, if you want manipulate with errors or results once you get them - you always may push error and results to new function, play with your data, and return the callback afterwards. Like so:
function(next)
{
new sql.Request()
.query('SELECT * from PERSON', (err, resultList) =>
{
if (err)
{
return next(err, null)
}
/*
data manipulation
*/
return next(null, resultList)
})
},

Categories