How to refactor this POST code from MySQL to PostgreSQL? - postgresql

I have this todo_list app built using:
Node.js
Express.js
EJS
MySQL
Choosing a database by following instructions from this Express website:
https://expressjs.com/en/guide/database-integration.html#mysql
https://expressjs.com/en/guide/database-integration.html#postgresql
I managed to make MySQL work with my todo_list app. But I'm having trouble refactoring the same CRUD (create) code for PostgreSQL use. Below is the working MySQL CRUD code and the unfinished PostgreSQL CRUD code for comparison. What am I doing wrong?
MySQL CRUD (create) code = works!
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
// _____________________________________________________________________________
// Add new list item - MySQL
let mysql = require('mysql');
let connection = mysql.createConnection({
host: 'localhost',
user: 'dbuser1',
password: '12345',
database: 'testdb1',
});
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO `todo_list` SET ?";
let query = connection.query(sql, data, function(err, results) {
if (err) throw err;
res.redirect('/');
});
});
PostgreSQL CRUD (create) code = doesn't work!
// .............................................................................
// Add new list item - PostgreSQL
// Loading and initializing the library without Initialization Options.
const pgp = require('pg-promise')();
const connection = {
user : 'pig1',
password : '12345',
host : 'localhost',
port : '5432',
database : 'todo_list'
};
// Database instance
const db = pgp(connection);
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO todo_list SET ?";
db.any(sql, data)
.then(results => {
console.log(`Inserted data into database!`);
console.log('DATA:', results);
res.redirect('/');
})
.catch(error => {
console.log('ERROR:', error);
})
.finally(db.$pool.end);
});

Thanks for the pointers! #vitaly-t #rabhi-salim
I managed to make the CRUD (create) code work with PostgreSQL now.
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
async function askStackOverflow() {
try {
await db.none('INSERT INTO todo_list(${this:name}) VALUES (${this:csv})', data);
// --- SUCCESS ---
console.log(``);
console.log(`Inserted data into database!`);
console.log(`DATA:`, insertedItem);
res.redirect('/');
} catch(error) {
// --- ERROR ---
console.log('ERROR:', error);
}
}
(async () => {
await askStackOverflow();
})();
});
Extra reading material:
Promises, Callback Hell, Async Await (ES7)
https://www.digitalocean.com/community/tutorials/javascript-promises-for-dummies
https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#insert-with-result
https://www.npmjs.com/package/pg-promise#named-parameters

Related

Import CSV file data into MongoDB using mongoose

I am building a full-stack application using MERN(MongoDB, Express, React, Node.js).
I have a .CSV file that I uploaded to MongoDB. However I can't get my routes to return any data.
I can see the database collection on my MongoDB cluster, But it's not showing up in my mongo shell.
My thought process is that's why I can't get my routes to work. How can I fix that?
sample .csv file data
Date,Client,Project,Project Code,Hours,Billable?,First Name,Last Name,Billable Rate
,,,,,,,,
4/3/17,Anil,Ethereum,RD001,3.84,No,Robert,Powell,0
4/3/17,Olith,Pharos,DV002,7.69,Yes,Hubert,Green,80
4/3/17,Olith,Pharos,DV002,4.46,Yes,Bradley,Hale,80
4/3/17,Olith,Pharos,DV002,7.57,Yes,Rudy,Parker,80
4/3/17,Prosaria,Business Development,GM001,0.92,No,Walter,Silva,0
As you can see the data exists in my mongo-atlas
But my mongo-shell is empty when I call db.clients.find()
server.js
const express = require('express');
const app = express();
const mongodb = require('mongodb').MongoClient;
const fs = require('fs');
const fastcsv = require('fast-csv');
const csvtojson = require('csvtojson');
require("dotenv").config()
const PORT = process.env.PORT || 3003;
//middleware
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(express.static(__dirname + 'public'));
// Global Configuration
const MONGODBURI = process.env.MONGODBURI || 'mongodb://localhost:27017/projectData';
let stream = fs.createReadStream('./gm_data.csv');
let csvData = [];
let csvStream = fastcsv
.parse()
.on('data', (data) => {
csvData.push({
date: data[0],
client: data[1],
project: data[2],
projectCode: data[3],
hours: data[4],
billable: data[5],
firstName: data[6],
lastName: data[7],
billableRate: data[8]
})
})
.on('end', () => {
csvData.shift();
console.log(csvData);
mongodb.connect(
MONGODBURI, {
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) throw err;
client
.db('gm-clients')
.collection('clients')
.insertMany(csvData, (err, res) => {
if (err) throw err;
console.log(`Inserted: ${res.insertedCount} rows`);
client.close
});
}
);
});
stream.pipe(csvStream);
//TEST ROUTE --- // http://localhost:3003/
app.get('/', (req, res) => {
res.send('Say Hello to Zee Server')
})
//routes
const customerRoutes = require('./routes/routes.js');
app.use('/customer', customerRoutes);
//Listening
app.listen(PORT, () => {
console.log('Listening on port', PORT)
})
routes.js
const express = require('express')
const router = express.Router();
const path = require('path');
let fs = require('fs');
let parse = require('csv-parse');
const csv = require('csvtojson');
const Customer = require('../models/customer.js');
//Index Route -- //http://localhost:3003/customer/allcustomers
router.get('/allcustomers', (req, res) => {
Customer.find({}, 'client', (err, data) => {
res.json({data: data});
})
})
module.exports = router;
models.js
const mongoose = require('mongoose')
const customerSchema = new mongoose.Schema({
name: String, //project col in CSV
clients: String, //client col in csv
hours: Number, // hours col in csv
billable_hours: Number, // billable col in csv
billable_amount: Number // billable rate in csv
})
// name | clients | hours | billable hours | billable amount
module.exports = mongoose.model('Customer', customerSchema);

Socket.io, Mongodb returning undefined to frontend

I want to use socekt.io for a new project I am building. I am using socket.io for a login component and will be using socket.io in the future to update pages like a chat app. I am also using mongoose to handle my mongodb connection. I am taking in a username, and returning a password to my front end to be bcryptjs compareSync hashed. The problem I am having is that whatever is returned to the front end is undefined. When I print out what is returned to the front end, it prints out the value I am looking for though. Something is going on between the backend emitting something, and the frontend receiving something but I don't know what is it exactly. Here is my code for the back end:
const express = require('express')
const socket = require('socket.io');
const http = require('http');
const router = require('./router');
const mongoose = require('mongoose');
let Player = require('../models/player.model');
require('dotenv').config();
const PORT = process.env.PORT || 5000;
const app = express();
const server = http.createServer(app);
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {useNewUrlParser: true, useCreateIndex: true,
useUnifiedTopology: true });
const connection = mongoose.connection;
connection.once('open',() => {
console.log('MongoDB database connection established successfully')
});
const io = socket(server);
io.on('connection', (socket) => {
console.log('We have a new connection');
socket.on('login', ({ username }, callback) => {
console.log(username);
Player.find({"username": username}, function (err, player) {
if(err) {
console.log("there has been an error"), {player: null}
}
socket.emit('id', { password: player[0]['password'].toString(), id : player[0]['_id']})
}) })})
app.use(router);
server.listen(PORT, () => console.log('Server is working'))
Here is my code for the front end:
const ENDPOINT = 'localhost:5000';
async function submitAccount (e) {
e.preventDefault();
socket.emit('login', { username });
socket.on("id", (response) => {
setPassword2(String(response['password']));
id = response['id']; console.log(id);
console.log(password2)
});
try {
if (bcrypt.compareSync(password, password2) == true) {
props.setCookie("id", id);
setAccess(true);
access2 = true;
console.log(access2)
console.log('works')
}
else {
setErrorType('Invalid Password')
setErrorMsg('There is an issue with your password. Please try again')
setOpenModal(true)
console.log(password);
console.log(password2);
}
}
catch {
setErrorType('Invalid Username')
setErrorMsg('This username does not exist. Please try another')
setOpenModal(true)
}
Thanks for the help!
When you do the socket.on, it should include the whole statement you are looking to change with the socket.io output. See below:
async function submitAccount (e) {
e.preventDefault();
socket.emit('login', { username });
socket.on("id", (response) => {
setPassword2(String(response['password']));
id = response['id']; console.log(id);
console.log(password2)
if (password2 != undefined) {
try {
if (bcrypt.compareSync(password, password2) == true) {
props.setCookie("id", id);
setAccess(true);
access2 = true;
console.log(access2)
console.log('works')
}
}

Express Sequelize Error - Cannot read property 'findAll' of undefined

I have successfully connected Sequelize and Express using Sequelize's github example with a few changes. I am now trying to do a simple Sequelize query to test the connection, but continue to receive an error stating that the model I have queried is not defined.
// ./models/index.js
...
const sequelize = new Sequelize(process.env.DB, process.env.DB_USER, process.env.DB_PASS, {
host: 'localhost',
dialect: 'postgres'
});
// Test SEQUELIZE connection
sequelize
.authenticate()
.then(() => {
console.log('Database connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
// ./routes/index.js
const models = require('../models');
const express = require('express');
const router = express.Router();
router.get('/contacts', (req, res) => {
models.Contact.findAll().then(contacts => {
console.log("All users:", JSON.stringify(contacts, null, 4));
});
});
module.exports = router;
// ./models/contact.js
const Sequelize = require('sequelize');
var Model = Sequelize.Model;
module.exports = (sequelize, DataTypes) => {
class Contact extends Model {}
Contact.init({
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'contact'
// options
});
return Contact;
};
The error I am getting when using postman to hit /contacts with a GET request is:
[nodemon] starting `node server.js`
The server is now running on port 3000!
Executing (default): SELECT 1+1 AS result
Database connection has been established successfully.
TypeError: Cannot read property 'findAll' of undefined
at router.get (C:\Users\username\desktop\metropolis\metropolis-backend\routes\index.js:6:20)
You are not requiring the model properly.
In ./routes/index.js add the next line:
const Contact = require('./models/contact.js');
And then call Contact.findAll()...
Second approach:
You can gather all your models by importing them into a loader.js file which you will store in the models directory. The whole job of this module is to import the modules together to the same place and then export them from a single place.
It will look something like that:
// loader.js
const modelA = require('./modelA');
const modelB = require('./modelB');
const modelC = require('./modelC');
...
module.exports = {
modelA,
modelB,
modelC,
...
}
And then you can require it in the following way:
in router/index.js:
const Models = require('./models');
const contact = Models.Contact;

API that fetches all records from mongoDB using express and mongoskin driver

I am beginner in Mean stack I am developing an API that fetches all records from mongodb using express. But I am not able to fetch all records from the database. I can't figure what I am doing wrong, I am doing it as follows:
This is my main app (server.js)
require('rootpath')();
var express = require('express');
var app = express();
var session = require('express-session');
var bodyParser = require('body-parser');
var expressJwt = require('express-jwt');
var config = require('config.json');
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(session({
secret: config.secret,
resave: false,
saveUninitialized: true
}));
// use JWT auth to secure the api
app.use('/api', expressJwt({
secret: config.secret
}).unless({
path: ['/api/users/authenticate', '/api/users/register']
}));
// routes
app.use('/', require('./controllers/login.controller'));
app.use('/register', require('./controllers/register.controller'));
app.use('/app', require('./controllers/app.controller'));
app.use('/api/users', require('./controllers/api/users.controller'));
/*// make '/app' default route
app.get('/', function (req, res) {
return res.redirect('/app');
});*/
// start server
var server = app.listen(3000, function() {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
This is my user.controller.js user will make a request to the api
http://localhost:3000/api/users/userList
var express = require('express');
var router = express.Router();
var userService = require('services/user.service');
router.get('/userList', getUserList);
module.exports = router;
function getUserList(req, res) {
userService.userList()
.then(function(users) {
if (users) {
res.send(users);
} else {
res.sendStatus(404);
}
})
.catch(function(err) {
res.status(400).send(err);
});
}
This is my user.service.js where I am querying the database to fetch all records using mongoskin driver.
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/EmployeeForm", {
native_parser: true
});
db.bind('users');
var service = {};
service.userList = userList;
module.exports = service;
function userList() {
var deferred = q.defer();
db.users.find(function(err, users) {
if (err) deferred.reject(err.name + ': ' + err.message);
});
return deferred.promise;
}
So i think it's find issue.
MongoDB find method return cursor by default.
https://docs.mongodb.com/manual/reference/method/db.collection.find/
From https://github.com/kissjs/node-mongoskin they use method toArray which will transform cursor into array of objects like this
db.find.toArray(callback)
So try like this in userList()
function userList() {
var deferred = q.defer();
db.users.find({}).toArray(function(err,docs){
err ? deferred.reject(err) : deferred.resolve(docs);
});
return deferred.promise;
}
Hope this helps.

How to connect to MongoDb with Hapi.js?

Does anyone know how to connect to MongoDb while using the Hapi.js framework?
I have only managed to find one example (https://github.com/Marsup/hapi-mongodb), but this requires using a plugin and has no comments in the code!
Does anyone know of a simpler way?
The following (using mongoose) works pretty well for me:
var Hapi = require('hapi');
var mongoose = require("mongoose");
var server = new Hapi.Server();
server.connection({ port: 3000 });
var dbUrl = 'mongodb://localhost:27017/mydb';
var dbOtions = {
db: { native_parser: true },
server: { poolSize: 5 }
};
server.register([ /* plugins */], function (err) {
if (err) {
throw err; // something bad happened loading the plugins
}
// ... Register the routes
server.start(function () {
mongoose.connect(dbUrl, dbOtions, function(err) {
if (err) server.log('error', err);
});
});
});
I use a hapi plugin that I wrote that connects to mongo, handles errors to log and adds bluebird promises.
'use strict';
var bluebird = require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));
exports.register = function(plugin, options, next) {
mongoose.connect(options.mongo.uri, options.mongo.options, function (e) {
if (e) {
plugin.log(['error', 'database', 'mongodb'], 'Unable to connect to MongoDB: ' + e.message);
process.exit();
}
mongoose.connection.once('open', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('connected', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('error', function (e) {
plugin.log(['error', 'database', 'mongodb'], 'MongoDB ' + e.message);
});
mongoose.connection.on('disconnected', function () {
plugin.log(['warn', 'database', 'mongodb'], 'MongoDB was disconnected');
});
});
return next();
};
exports.register.attributes = {
name: 'mongoose',
version: '1.0.0'
};
Blog post on user authentication with passport and Mongoose
Also be aware that Hapi's model is based off of plugins so read and re-read the docs on building your own.
Visit http://cronj.com/blog/hapi-mongoose
Complete sample project which can help you Repo Link https://github.com/gauravgupta90/Hapi-Mongoose-Angular
Config.js
module.exports = {
server: {
host: '0.0.0.0',
port: 8000
},
database: {
host: '127.0.0.1',
port: 27017,
db: 'DatabaseName',
username: '',
password: ''
}
};
Server.js
var Hapi = require('hapi'),
Routes = require('./routes'),
config = require('./config'),
Db = require('./database');
var server = Hapi.createServer(config.server.host, config.server.port, {
cors: true
});
server.route(Routes.endpoints);
server.start(function() {
console.log('Server started ', server.info.uri);
});
Database.js
var Mongoose = require('mongoose'),
config = require('./config');
Mongoose.connect('mongodb://' + config.database.host + '/' + config.database.db);
var db = Mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function callback() {
console.log("Connection with database succeeded.");
});
exports.Mongoose = Mongoose;
exports.db = db;
The following works for me:
const Hapi = require("hapi");
const Mongoose = require("mongoose");
const server = new Hapi.Server({ "host": "localhost", "port": 3000 });
Mongoose.connect('mongodb://localhost:27017/testdb', { useNewUrlParser: true }, (err) => {
if (!err) { console.log('MongoDB Connection Succeeded.') }
else { console.log(`Error in DB connection : ${err}`)}
});