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

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;

Related

MERN stack : Express api returning empty data , but the data is already present in mongodb

I am new to the MERN stack, and I have been trying to access my collections in MongoDB.
Here is the code for the router, view bookings:
/*This is router file*/
var mongoose = require('mongoose');
const express = require('express');
const bodyParser = require('body-parser')
let book = require('../models/BookTravel');
const router = require('express').Router()
router.use(express.json())
router.route('/').get((req, res) => {
// Company.aggregate({companyId})
book.find()
.then((result) => {
console.log(result)
return res.status(200).json(result)
})
})
module.exports = router;
/*
* this is for model
*/
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const TravelSchema = new Schema({
firstname:{
type: String,
required: true
},
bookingId:{
type: String,
required: true
},
lastname:{
type: String,
required: true
},
startcity:{
type: String,
required: true
}
})
const travel = mongoose.model('travel', TravelSchema)
module.exports = travel;
////in app.js file
const viewBookings = require('./routes/viewBookings');
app.use('/viewBookings', viewBookings)
The postman is also giving empty result.
What am I missing out ? Is it not possible to access the already existing collection with this method ?
You are missing some code in the router file.
for example! If you want to get data from a database
you can simply use like below this
.......
router.get("/",async (req,res)=>
{
try{
const result = await book.find();
res.status(200).json({"message" : result})
}
catch(error)
{
console.log(error)
}
})
......

Mongoose getters are either not working the way I want or I'm misunderstanding what they are

I created some sample code to demonstrate my issue on a smaller scale. From my understanding, a getter function will not affect anything on my database, but when I want to make a get request to view items on my database, it will change the value to whatever is returned only when the data is displayed. However, when I make my get request to view items on my database, the item I am shown is exactly how it was saved. I'm not sure if I'm misunderstanding what a getter function is, or if my syntax is just incorrect somewhere.
Here is my main server:
const express = require('express')
const mongoose = require('mongoose')
// Linking my model
const User = require('./User')
// Initializing express
const app = express()
const PORT = 9999
app.use(express.json())
// Connecting to mongodb
const connectDB = async () => {
try {
await mongoose.connect('mongodb://localhost/testdatabase', {
useUnifiedTopology: true,
useNewUrlParser: true
})
console.log('Connected')
} catch (error) {
console.log('Failed to connect')
}
}
connectDB()
// Creates a new user
app.post('/user/create', async (req, res) => {
await User.create({
name: 'John Cena',
password: 'somepassword'
})
return res.json('User created')
})
// Allows me to view all my users
app.get('/user/view', async (req, res) => {
const findUser = await User.find()
return res.json(findUser)
})
// Running my server
app.listen(PORT, () => {
console.log(`Listening on localhost:${PORT}...`)
})
Here is my model:
const mongoose = require('mongoose')
// My setter - initialPassword is 'somepassword'
// This seems to work properly, in my database the password is changed to 'everyone has the same password here'
const autoChangePassword = (initialPassword) => {
console.log(initialPassword)
return 'everyone has the same password here'
}
// My getter - changedPassword should be 'everyone has the same password here' I think
// The console.log doesn't even run
const passwordReveal = (changedPassword) => {
console.log(changedPassword)
return 'fakehash1234'
}
// Creating my model
const UserSchema = mongoose.Schema({
name: {
type: String
},
password: {
type: String,
set: autoChangePassword,
get: passwordReveal
}
})
// Exporting my model
const model = mongoose.model('user', UserSchema)
module.exports = model
Not sure if it would help anyone since I found my answer on another StackOverflow post, but the issue was I had to set getters to true when converting back to JSON:
// Creating my model
const UserSchema = mongoose.Schema({
name: {
type: String
},
password: {
type: String,
set: autoChangePassword,
get: passwordReveal
}
}, {
toJSON: { getters: true }
})
Any similar problems can be solved by adding some combination of the following:
{
toJSON: {
getters: true,
setters: true
},
toObject: {
getters: true,
setters: true
}
}

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);

Create not found when using Sequelize CLI generated model

My approach was like this below command
npx sequelize-cli model:generate --name User --attributes name:string,email:string,password:string
then it's generated a model file named user.js & file structure like below
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
User.hasMany(models.Course, {
foreignKey: 'userId'
})
}
};
User.init({
name: DataTypes.STRING
}, {
sequelize,
modelName: 'User',
});
return User;
};
also, created the Users table with columns.
And the index.js file like below which automatically generated
'use strict';
// main model file
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
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;
and when I try to create a user like the below codes
import { User } from '../../../../models'
try {
await User.create({
name: 'john doe',
email: 'john#gmail.com'
})
res.json({"message": "create"})
} catch (error) {
res.send(error.message)
}
it's showing
Cannot read property 'create' of undefined
what I have done wrong here?
Can you please help me out with that?
Thanks
replace this code in models/index.js for printing database successfully connected or not.
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../../config/config.js')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
//for checking database successfully connected or not
sequelize
.authenticate()
.then(() => {
console.log('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 => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
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;
Then try to importing like this.
const admin = require("../../database/models").tbl_admin;
try {
await admin.create({
name: 'john doe',
email: 'john#gmail.com'
})
res.json({"message": "create"})
} catch (error) {
res.send(error.message)
}

How to refactor this POST code from MySQL to 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