How to make multy queries on mysql with node.js - mysql

I'm trying to run 2 queries against a MySQL database and they are not working. And display it, getting errors, can I do this a better way? I'm mainly asking how to display it in the home.handlebars file and how to make more than 1 query from MySQL database.
var express = require('express');
var handlebars = require('express-handlebars');
var bodyParser = require('body-parser')
var mysql = require('mysql');
var app = express();
app.engine('handlebars', handlebars({defaultLayout: 'main'}));
app.set('views', __dirname + '/views');
app.set('view engine', 'handlebars');
app.use(express.static('public'));
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'translation_project'
});
connection.connect();
app.get('/', function(req, res) {
var translatorid = 45;
var sqlQuery = "SELECT title,type FROM itemtable;"
connection.query(sqlQuery,function(err,rows,fields){
if(err){
console.log('Error'+err);
}else{
res.render('home',{items:rows}); // to be displayed in the home page
}
});
var sqlQuery2 = "SELECT dateoftranslation FROM translateditems;"
connection.query(sqlQuery2,function(err,rows,fields){
if(err){
console.log('Error'+err);
}else{
res.render('home',{dates:rows}); // to be displayed in the home page
}
});
});
app.listen(3000, function() {
console.log('Server is running at port 3000');
});
and Here is the home.handlebars file
<h1> My Applied Items </h1>
{{#each items}} <!-- the items refreneced in the index page-->
<p>{{title}}</p>
<p>{{type}}</p>
{{/each}}
{{#each dates}} <!-- the dates refreneced in the index page-->
<p>{{dateoftranslation}}</p>
{{/each}}
and Here is the home.handlebars file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Users Profile</title>
</head>
<body>
<h1> Mohamed </h1>
{{{body}}}
</body>
</html>

I would consider using Promises so you can wait for both queries to return before sending the result to the client:
function query(sqlQuery) {
return new Promise(function (resolve, reject) {
connection.query(sqlQuery, function (err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
app.get('/', function (req, res) {
var query1 = query("SELECT title,type FROM itemtable;");
var query2 = query("SELECT dateoftranslation FROM translateditems;");
Promise.all(query1, query2).then(function (result) {
res.render('home', {
items: result[0],
dates: result[1]
});
});
});

You should do it in callback nesting due to asynchronous nature of connection.query().
app.get('/', function(req, res) {
var translatorid = 45;
var sqlQuery = "SELECT title,type FROM itemtable;",
sqlQuery2 = "SELECT dateoftranslation FROM translateditems;";
connection.query(sqlQuery,function(err,rows1){
if(err){
console.log('Error'+err);
}
else{
connection.query(sqlQuery2,function(err,rows2){
if(err){
console.log('Error'+err);
}
else{
res.render('home',{items:rows1,dates:rows2});
}
});
}
});
});
If you are performing several queries and you don't want Callback nesting(Due to non-readability of multi-nesting callbacks) then you should try promise or you can do that async way.
below is async way.
var async=require('async');
connection.connect();
app.get('/', function(req, res) {
var translatorid = 45;
var sqlQuery = "SELECT title,type FROM itemtable;",
sqlQuery2 = "SELECT dateoftranslation FROM translateditems;",
sqlQuery3="someQuery",
sqlQuery4="someOtherQuery",
sqlQuery5="someOtherOtherQuery";
async.parallel([function(cb){
connection.query(sqlQuery,function(err,rows1){
if(err){
console.log('Error'+err);
cb(err);
}
else{
cb(null,rows1);
}
});
},function(cb){
connection.query(sqlQuery2,function(err,rows2){
if(err){
console.log('Error'+err);
cb(err);
}
else{
cb(null,rows2);
}
});
},function(cb){
connection.query(sqlQuery3,function(err,rows3){
if(err){
console.log('Error'+err);
cb(err);
}
else{
cb(null,rows3);
}
});
},function(cb){
connection.query(sqlQuery4,function(err,rows4){
if(err){
console.log('Error'+err);
cb(err);
}
else{
cb(null,rows4);
}
});
},function(cb){
connection.query(sqlQuery5,function(err,rows5){
if(err){
console.log('Error'+err);
cb(err);
}
else{
cb(null,rows5);
}
});
}],function(err,results){
if(err){
// out of those 5 tasks at least one caused some error.
// handle that.
return;
}
// no error occurred.
var rows1=results[0],
rows2=results[1],
rows3=results[2],
rows4=results[3],
rows5=results[4];
res.render('home',{items:rows1,dates:rows2,other1:rows3,other2:rows4,other3:rows5});
});
});

Related

Where to place code to show data from MySQL to Handlebars?

Goal:
I am aiming to teach myself how to use Node JS, MySQL and express.
I'm struggling to understand where to place my code for loading MySQL data into HTML.
Let me show you the whole code.
app.js
var express = require('express');
var mysql = require('mysql');
var dotenv = require('dotenv');
var path = require('path');
var cookieParser = require('cookie-parser');
dotenv.config({path: './.env'});
var app = express();
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
db.connect(function(error) {
if(error) {
console.log(error);
}
else{
console.log("Connected");
}
});
// Parse URL-Encoded bodies
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies
app.use(express.json());
// Initialize a cookie
app.use(cookieParser());
// View engine to control HTML
app.set('view engine', 'hbs');
// Public dir
var publicDir = path.join(__dirname, './public');
app.use(express.static(publicDir));
// Define routes
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));
app.listen(3000, function() {
console.log("Server is running on port 3000");
});
routes/pages.js
var express = require('express');
var authController = require('../controllers/auth');
var router = express.Router();
// Home
router.get("/", authController.isLoggedIn, function(req,res) {
res.render("index", {
user: req.user
});
});
// Register
router.get("/register", function(req, res) {
res.render("register");
});
// Login
router.get("/login", function(req, res) {
res.render("login");
});
// Profile
router.get('/profile', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('profile', {
user: req.user
});
}
else {
res.redirect('login');
}
});
// Forum
router.get('/forums', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('forums');
} else {
res.redirect('login');
}
});
// English Division //
// Premier League
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('PremierLeague');
} else {
res.redirect('../../login');
}
});
module.exports = router;
routes/auth.js
var express = require('express');
var authController = require('../controllers/auth');
var router = express.Router();
// Register
router.post("/register", authController.register);
// Login
router.post("/login", authController.login);
// Logout
router.get('/logout', authController.logout);
module.exports = router;
controllers/auth.js
var mysql = require('mysql');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var {promisify} = require('util');
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
// Register function
exports.register = function(req, res) {
console.log(req.body);
var {name, email, password, passwordConfirm} = req.body;
db.query("SELECT email FROM users WHERE email = ?", [email], function(error, result) {
if(error){
console.log(error);
}
if(result.length > 0) {
return res.render('register', {
message: 'That email is already in use'
})
} else if(password !== passwordConfirm) {
return res.render('register', {
message: 'Passwords do not match'
});
}
let hashedPassword = bcrypt.hashSync(password, 8);
console.log(hashedPassword);
// Insert user details into MySQL
db.query('INSERT INTO users set ?', {name: name, email: email, password: hashedPassword, dateJoined: new Date()}, function(error, result) {
if(error) {
console.log(error);
} else {
console.log(result);
return res.render('register', {
message: 'User registered'
});
}
});
});
}
// Login function
exports.login = function(req, res) {
try {
var {email, password} = req.body;
if(!email || !password) {
return res.status(400).render('login', {
message: 'Please provide an email and password'
});
}
db.query('SELECT * FROM users WHERE email = ?', [email], async function(error, result) {
console.log(result);
if(!result.length > 0 || !(await bcrypt.compare(password, result[0].password))) {
res.status(401).render('login', {
message: 'The email or password is incorrect'
});
}
else {
var id = result[0].id;
// Create a token
var token = jwt.sign({id}, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
console.log("The token is " + token);
// Create a cookie
var cookieOptions = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true
}
// Set up a cookie
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect("/");
}
});
} catch (error) {
console.log(error);
}
}
// Check if logged in
exports.isLoggedIn = async function(req, res, next) {
console.log(req.cookies);
if(req.cookies.jwt){
try {
// Verify the token
var decoded = await promisify(jwt.verify)(req.cookies.jwt, process.env.JWT_SECRET);
console.log(decoded);
// Check if user exist
db.query("SELECT id, name, email, password, date_format(datejoined, '%d/%m/%Y') as dateJoined FROM users WHERE id = ?", [decoded.id], function(error, result) {
console.log(result);
// If no result
if(!result) {
return next();
}
req.user = result[0];
return next();
});
}
catch (e) {
console.log(e);
return next();
}
} else{
next();
}
}
// Logout function
exports.logout = async function(req, res) {
res.clearCookie('jwt');
res.status(200).redirect('/');
}
Question
In my .hbs file called PremierLeague I'd like to load MySQL data in HTML format. Where in the code below I need to start?
Desired goal:
This is when the user clicks into view premier league
Foreach record in MySQL I'd like to add a new card for each record. I know how to use HandleBars {{some.data}}.
I just don't get where I code the query?
Does it needs to be in a controller or can it be in in the router.get(...?
Also how do I use {{#foreach}} correctly ?
You don't need any other specific controller, the right place to code the query is actually the route itself.
But before entering the core of your question, let's talk a while about your code.
I can see you are performing connection to database more than once, you could add database dedicated controller, something like:
controllers/db.js
var mysql = require('mysql');
var dotenv = require('dotenv');
dotenv.config({path: './.env'});
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
function connect(done) {
db.connect(done);
}
module.exports = { db: db, connect: connect };
this let you access to the database instance from every file with just one line:
var db = require('./controllers/db').db;
than you could use the connect function in your app:
app.js
var express = require('express');
var db = require(./controllers/db);
var path = require('path');
var cookieParser = require('cookie-parser');
// set up your server
var app = express();
// Parse URL-Encoded bodies
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies
app.use(express.json());
// Initialize a cookie
app.use(cookieParser());
// View engine to control HTML
app.set('view engine', 'hbs');
// Public dir
var publicDir = path.join(__dirname, './public');
app.use(express.static(publicDir));
// Define routes
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));
// finally run your server only if you can connect to the database
db.connect(function(error) {
if(error) return console.log("Error connecting to the database:", error);
app.listen(3000, function() {
console.log("Server is running on port 3000");
});
});
you could also simplify you controllers/auth.js removing database connection stuff and using only the line to require your database controller.
Finally you can code your query:
routes/pages.js
var express = require('express');
var authController = require('../controllers/auth');
var db = require('../controllers/db').db;
var router = express.Router();
// Omissis... other routes
// Premier League
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
// a good practice is first to handle possible exit cases to reduce nesting levels
if(! req.user) return res.redirect('../../login');
// this is actually the right place to perform queries
db.query('SELECT ...', [...], function(error, results) {
// once again first possible exit cases
if(error) return res.status(500).end(error.message)
res.render('PremierLeague', { results: results });
});
});
module.exports = router;
Last in your PremierLeague.hbs file you can handle the results in a #foreach directive.
Just pass your data when you render the view
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
if(req.user) {
connection.query('SELECT * FROM EnglishDivision',function (err,results) {
if (err) throw err;
res.render('PremierLeague',{data: results});
});
} else {
res.redirect('../../login');
}
});
then in the .hbs file
{{#each data}}
<div class="card">
<h3>{{this.someData}}</h3>
<h2>{{this.someData}}</h2>
</div>
{{/each}}

using MYSQL data is getting in console but not rendering on HTML pages

I am creating a CRUD using MySQL, Node, AngularJS, and Express.
I am getting the response in the consoles but the data is not rendering in HTML pages.
The below-attached picture is the list of employees which is displayed on the HTML page as well as getting responses too: Displaying all employees
To get the details of the particular employee, click on show button. But by clicking on show button the data is showing in the consoles but not displaying in the HTML pages: Displaying employee details based on id
The code is as follows:
show.html
<div class="panel panel-default" ng-init="showEmployee()">
<div class="panel-heading">
<p class="panel-title"> Employee Detail Information</p>
</div>
<div class="panel-body">
<form>
<div class="form-group" ng-controller="empController">
<label class="form-control">Name: {{ employee.name }}</label>
<label class="form-control">Email: {{ employee.email }}</label>
<label class="form-control">Position: {{ employee.position }}</label>
<label class="form-control">Contact: {{ employee.contact }}</label>
<label class="form-control">ID: {{ employee.id }}</label>
Cancel
</div>
</form>
<div>
<div>
app.js
var myApp = angular.module('myApp',['ngRoute']);
myApp.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl:'templates/list.html',
controller:'empController'
})
.when('/employees', {
templateUrl:'templates/list.html',
controller:'empController'
})
.when('/employees/create', {
templateUrl:'templates/add.html',
controller:'empController'
})
.when('/employees/update/:id', {
templateUrl:'templates/edit.html',
controller:'empController'
})
.when('/employees/:id/show', {
templateUrl:'templates/show.html',
controller:'empController'
});
});
controller.js
myApp.controller('empController', function($scope,$route,$routeParams,$http){
$scope.getEmployees = function(){
$http.get('/employees').then(function(response){
console.log(response)
$scope.employees = response.data;
});
};
$scope.showEmployee = function(){
var id = $routeParams.id;
$http.get('/employees/'+ id).then(function(response){
console.log(response);
$scope.employee = response.data;
});
};
$scope.addEmployee = function(){
$http.post('/employees/create', $scope.employee).then(function(response){
//$scope.employee = response.data;
window.location.href = '/';
});
};
$scope.updateEmployee = function(){
var id = $routeParams.id;
$http.put('/employees/update/'+ id , $scope.employee).then(function(response){
window.location.href = '/';
});
};
$scope.deleteEmployee = function(id){
var id = id;
$http.delete('/employees/'+ id).then(function(response){
$route.reload();
});
};
});
server.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var mysql = require('mysql');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/client'));
//start mysql connectio
var connection = mysql.createConnection({
host:'localhost',
user: 'root',
password:'12345',
database:'Employee'
});
connection.connect(function(err) {
if (err) throw err
console.log('You are now connected...')
})
//end mysql connectionselected
app.get('/employees', function(req, res){
connection.query("SELECT * FROM employees", function(err,results) {
if(err){
console.log(err);
res.json({"error": true});
}
else{
console.log(results);
res.end(JSON.stringify(results));
}
})
//}
//})
});
app.get('/employees/:id', function(req, res){
console.log(req);
connection.query('select * from employees where id=?', [req.params.id], function (error, results, fields) {
if (error) throw error;
console.log(results);
res.end(JSON.stringify(results));
});
});
app.post('/employees/create', function(req, res){
var postData = req.body;
connection.query('INSERT INTO employees SET ?', postData, function (error, results, fields) {
if (error) throw error;
res.end(JSON.stringify(results));
});
});
app.delete('/employees/:id', function(req, res){
console.log(req.body);
connection.query('DELETE FROM `employees` WHERE `id`=?', [req.body.id], function (error, results, fields) {
if (error) throw error;
res.end('Record has been deleted!');
});
});
app.put('/employees/update/:id', function(req, res){
app.put('/employees', function (req, res) {
connection.query('UPDATE `employees` SET `name`=?,`email`=?,`position`=?,`contact`=? where `id`=?', [req.body.name,req.body.email, req.body.position, req.body.contact, req.body.id], function (error, results, fields) {
if (error) throw error;
res.end(JSON.stringify(results));
})
});
});
app.listen(3000, function(){
console.log('server is running on port 3000..');
});
Can anyone please help me out?
Thank you in advance
$scope.showEmployee = function(){
var id = $routeParams.id;
$http.get('/employees/'+ id).then(function(response){
console.log(response);
// $scope.employee = response.data;
$scope.employee = response.data[0];
});
};

If I console.log my results it shows up, but if I return it it doesn't

My return result doesn't make it all the way back to API endpoint.
Do you see what I'm doing wrong?
app.js
const express = require('express');
const app = express();
app.use(express.static('client'));
var GetContracts = require('./contractsService');
app.get('/contracts', async (req, res) => {
var results = await GetContracts.get();
console.log(results);
res.send(results);
});
module.exports = app;
contractsService.js
var mysql = require('mysql');
const config = require('./config')
var con = mysql.createConnection({
host: config.HOST,
user: config.USER,
password: config.PASSWORD,
database: config.DATABASE
});
exports.get = function () {
con.connect(function (err) {
if (err) {
throw new Error('Error by Rodney')
};
con.query("SELECT * FROM " + config.DATABASE + ".Contracts", function (err, result, fields) {
if (err) {
throw new Error('Error by Rodney')
};
return result;
//console.log(result); //works
});
});
}
query method accepts error-first callback that isn't affected by returned value. GetContracts.get doesn't return a promise, and awaiting won't do anything.
It should be promisified in order to be used in promise control flow:
exports.get = function () {
return new Promise((resolve, reject) => {
con.connect(function (err) {
if (err) {
reject(new Error('Error by Rodney'))
};
con.query("SELECT * FROM " + config.DATABASE + ".Contracts", function (err, result, fields) {
if (err) {
reject(new Error('Error by Rodney'));
} else
resolve(result);
});
});
});
}
Or preferably, use existing promise-based MySQL library like promise-mysql, something like:
var mysql = require('promise-mysql');
const conPromise = mysql.createConnection({
host: config.HOST,
user: config.USER,
password: config.PASSWORD,
database: config.DATABASE
});
exports.get = async () => {
const con = await conPromise;
const result = await con.query("SELECT * FROM " + config.DATABASE + ".Contracts");
return result;
};

mysql million rows express.js slow response

I am using node.js v0.10.33 with node-mysql 2.5.4 and express.js 4.10.2 and fast-csv 0.6.0
Any following requests made to the server slows down after a request to "query 9000000 rows and download it as csv". Is there a better way to avoid the slow response?
/**
* problem is why the server response slows down on a large request mande to mysqlrows_to_csv which queries 9000000 rows and saves as csv
*/
(function () {
'use strict';
var async = require('async');
var csv = require("fast-csv");
var fs = require('fs');
var mysql = require('mysql');
//var express = require('express');
//var expRouter = express.Router(); // Express Router
expRouter.get('/mysqlrows_to_csv/', function(req, res, next) {
mysqlrows_to_csv(function(err) {
console.log('use socket to emit a notification to client saying csvfile is ready');
});
res.json({'mysqlrows_to_csv': true});
return res.end();
});
expRouter.get('/some_other_queries/', function(req, res, next) {
res.json({'some_other_queries': true});
return res.end();
});
function mysqlrows_to_csv(callback) {
var csvStream;
var connProp = {
host : 'host',
user : 'user',
password : 'password',
database : 'database'
};
var I = 0;
async.waterfall([
function(cb) {
var connection = mysql.createConnection(connProp);
connection.connect(function(err) {
if (err) return callback(err);
csvStream = csv.createWriteStream({headers: true});
var writableStream = fs.createWriteStream("dump_mysql_to_csv.csv");
writableStream.on("error", function(err){
return callback(err);
});
writableStream.on("finish", function(){
console.log("DONE!");
return callback(null);
});
if (csvStream) csvStream.pipe(writableStream);
return cb(err, connection);
});
},
function(connection, cb) {
var qry = 'select * from table'; // this has aleast 9000000 rows
var query = connection.query(qry);
query
.on('error', function(err){
return cb(err);
})
.on('result', function(row) {
connection.pause();
I = I + 1;
console.log('row no.', I);
if (csvStream) csvStream.write(row);
connection.resume();
})
.on('end', function() {
console.log('stream-ended')
if (csvStream) csvStream.end();
return cb(null, connection);
});
},
function(connection, cb) {
connection.end(function(err) {
if (err) {
console.log('Error while disconnecting mysql', err);
}
console.log('The connection is terminated now');
console.log('final conn state:', connection.state);
});
}
]);
}
}());

Creating a new model doesn't work - no error

i am using node-orm2 with mysql in my project. I have already created the database tables, and i can query/find data in my DB. However, when i want to insert new data, nothing happens - no error in the callback, nothing.
Here is the relevant code:
Model class:
module.exports = function (orm, db) {
var Comment = db.define('comment', {
body: {type: 'text'}
});
};
Index.js in the model folder:
var orm = require('orm');
var settings = require('../config/settings');
var connection = null;
function setup(db, cb) {
require('./comment')(orm, db);
return cb(null, db);
}
module.exports = function (cb) {
if (connection) return cb(null, connection);
orm.connect(settings.database, function (err, db) {
if (err) return cb(err);
connection = db;
db.settings.set('instance.returnAllErrors', true);
db.settings.set('connection.debug', true);
setup(db, cb);
});
};
Controller:
var orm = require('orm');
exports.create = function(req, res){
var testcomment = {};
testcomment.body = "test comment";
req.models.comment.create(testcomment, function (err, message) {
if (err) return console.log(err);
return res.send(200, message);
});
};
Environment.js
var path = require('path');
var express = require('express');
var settings = require('./settings');
var models = require('../models/');
var logger = require('morgan');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
module.exports = function (app) {
app.use(express.static(path.join(settings.path, 'public')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride());
app.use(function (req, res, next) {
models(function (err, db) {
if (err) return next(err);
req.models = db.models;
req.db = db;
return next();
});
})
};
Settings.js:
var path = require('path');
var settings = {
path : path.normalize(path.join(__dirname, '..')),
port : process.env.NODE_PORT || 3001,
database : {
protocol : "mysql",
host : "localhost",
port : "3306",
database : "taxidatabase",
user : "root",
password : "admin"
}
};
module.exports = settings;
I basically followed the pattern in the example application in node-orm2 - but it doesn't work. Any idea, why?
Thanks!
Before adding anything to table you need to sync the DB at least once after you define the models in order to create the tables:
var models = require('../app/models/');
models(function (err, db) {
if (err) throw err;
db.sync(function (err) {
if (err) throw err;
console.log('Done!');
});
});
Or maybe syncing the comment model will do:
var orm = require('orm');
exports.create = function(req, res){
var testcomment = {};
testcomment.body = "test comment";
req.models.comment.create(testcomment, function (err, message) {
if (err) return console.log(err);
return res.send(200, message);
});
req.models.comment.sync(function (err) {
if (err) throw err;
console.log('Done!');
});
};