Sequelize ORM can't use sync() - node.js

This is an extract from a file that uses db as the variable from the db.js file, which is the file which connects to the database. And this works fine.
const Sequelize = require("sequelize")
const db = require("../database/db.js")
module.exports = db.sequelize.define(
"physics_tbls", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},...
When I add db.sync() to the end of this file, I get an error. This is the end of file above,
.......
Sub_part: {
type: Sequelize.STRING
}
}, {
timestamps: false
}
)
db.sync({
// force: true
})
.then(() => {
console.log('Connection to database established successfully.');
})
.catch(err => {
console.log('Unable to connect to the database: ', err);
})
I get the error,
TypeError: db.sync is not a function
If db.sequelize works why does db.sync() not work?
Perhaps db.sync should be in the same file as db.js which contains the variable db.But I do need to define my models before I can sync().
This is db.js
const Sequelize = require("sequelize")
const db = {}
const sequelize = new Sequelize("physics_papers_db", "root", "********", {
host: "localhost",
dialect: "mysql",
// operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
My Express routes incidentally are in another file called tasks.js
const Sequelize = require('sequelize')
var express = require("express")
var router = express.Router()
const Task = require("../model/Task")
//Test
router.get("/test", (req, res) => {
Task.findAll({
//Use attributes to only select specific fields
attributes: ['Question', 'Marks']
})
.then(tasks => {
console.log("router.get(\"/test\", (req, res) => {...");
console.log("All tasks:", JSON.stringify(tasks, null, 4));
res.json(tasks)
})
.catch(err => {
res.send("error: " + err)
})
})
........... more routes...
module.exports = router
Thanks,

#l2ysho answer is right, but I would add a bit of work so you can avoid the "mess" you are doing in your code... when using an ORM, the general idea is to help us, not only connect to the database, or not writing any SQL, or protect from SQL injection, but mostly be easy to use and change...
with that in mind, always do this when using Sequelize:
create a models folder in your project
add an index.js inside that folder with:
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const _ = require('lodash');
const db = {};
const sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USER, process.env.DB_PWD, {
host: process.env.DB_HOST,
dialect: 'mysql',
logging: process.env.APP_ENVIRONMENT !== 'local' ? null : console.log,
pool: {
max: 5,
min: 0,
idle: 10000,
},
operatorsAliases: false,
});
// add all models
fs.readdirSync(__dirname)
.filter(file => file.indexOf('.') !== 0 && file !== 'index.js' && file.slice(-3) === '.js')
.forEach(file => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
// add all associations
Object.keys(db).forEach(modelName => {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
module.exports = _.extend(
{
sequelize,
Sequelize,
},
db
);
now, add a file per database model, let's imagine a logs table you might have:
called it logs.js and put inside the models folder, together with the index.js
module.exports = (sequelize, DataTypes) => {
const model = sequelize.define(
'external_logs',
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
engine: { type: DataTypes.STRING, allowNull: false },
response_code: { type: DataTypes.INTEGER.UNSIGNED, allowNull: true },
origin: { type: DataTypes.STRING, allowNull: true },
created_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
},
},
{
timestamps: false,
tableName: 'frontend_api_external_logs',
}
);
model.associate = models => {
model.belongsTo(models.campaigns, {
foreignKey: 'campaign_id',
allowNull: false,
onDelete: 'cascade',
onUpdate: 'cascade',
});
model.belongsTo(models.external_audit, {
foreignKey: 'audit_id',
allowNull: false,
onDelete: 'cascade',
onUpdate: 'cascade',
});
};
return model;
};
as you can see, you can easily create associations with other models very easy, without the need to import any file, and you can then call this model, by the definition you specified, in this case: external_logs ... though the real table name is called, as you can see: frontend_api_external_logs
if you end up needed to call any model or perform any database task, all you need is to call that index.js file, and not only the database, but also all models with their own associations will be available as well... for example, in a utilities folder, with a database.js file, the database.js could simply have:
const db = require('./../models'); // same as './../models/index'
const logApiCall = (action, description) => {
const logRow = {
// content of the external logs table
external_audit: {
// content of the audit table as there's an association
}
}; // the content
db.external_logs
.create(logRow, { include: db.external_audit })
// inserted
})
.catch(err => {
// NOT inserted
logger.log(`AUDIT ERROR: ${err.message}`);
utilities.slack.sendMessage({ action, description, error: err.message });
});
};
exports.logCall = logApiCall;
and this makes it even easier to perform logs with audits to any action performed by the users, and it will as simple as:
const db = require('./../utilities/database');
...
db.logCall('my action', 'my description');
as you can see, I don't need to worry about what models my file is (no need to require each model I'm using) and I simply call one file that handles all.
this is what I've been using since I've started to use Sequielize (when there was only v2 available) and I've been "upgrading" the index.js file when they bump versions, but this one is the exact same for ev4 and the new v5...
give it a try and I'm sure it will help you along your Sequielize projects...
in a new project of mine:

It is correct behaviour, you export sequelize instance and Sequelize class, so you should use db.sequelize.sync()

Related

Error("No Sequelize instance passed") No Sequelize instance passed

Hello can somebody help me with this ? I was doing my controllers and I can access to my model like this "const { User } = require("../models/User");" but than when I send my request I had this message "TypeError: Cannot read property 'create' of undefined" so something was missing.
So I change my call model to this "const { User } = require("../models");".
And I went on my model index.js (so connection sequelize) and I add fs function and Objectif.key. After all those changes I have the error "No Sequelize instance passed".
So maybe somebody can help with this because I don't see the problem
So this is my model index.js
//sequelize importe
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const db = {};
const basename = path.basename(__filename);
let sequelize = new Sequelize("groupomania", "root", "root", {
host: "localhost",
dialect: "mysql",
});
sequelize
.authenticate()
.then(() => {
console.log("Connection has been established successfully!");
})
.catch((err) => {
console.log("Can't establish database connection:\n" + err);
});
fs.readdirSync(__dirname)
.filter((file) => {
console.log( file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js");
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;
This is my model User.js
const { Model } = require("sequelize");
module.exports = (Sequelize, DataTypes) => {
class User extends Model {
toJSON() {
return {
...this.get(),
password: undefined,
};
}
}
User.init(
{
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4 },
nom: { type: DataTypes.STRING, allowNull: false },
prenom: { type: DataTypes.STRING, allowNull: false },
email: {
type: DataTypes.STRING,
allowNull: false,
validate: { notNull: true, notEmpty: true, isEmail: true },
},
status: { type: DataTypes.STRING, allowNull: false },
password: { type: DataTypes.STRING, required: true },
},
{ Sequelize, tableName: "users", modelName: "User" }
);
return User;
};
My controllers/user.js
/*const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");*/
const { User } = require("../models/User");
module.exports.signup = async (req, res) => {
try {
const user = await User.create({
nom: "Jp",
prenom: "remy",
email: "remy#gmail.fr",
password: "motdepasse",
});
res.status(200);
throw Error("erreur est survenu");
} catch (erreur) {
console.log(erreur);
res.status(200).json({ erreur });
}
};
My route user
const express = require("express");
const router = express.Router();
const userCtrl = require("../controllers/user");
router.post("/signup", userCtrl.signup);
/*router.post("/login", userCtrl.login);*/
module.exports = router;
Thank you for any help! :)
The answer was that on my model user the "S" of sequelize must have an s minus

Unable to develop assosciations between models in sequelize

I am creating realtionship (one to many) between User model and Task model
I have crated the reference column in the migration too
I am using sequlize ORM with sequelize cli. Everything works fine when I try alternative method that i will explain later but If i try to do it according the documentation it gives me error
Task is not associated to User
WORKING ALTERNATIVE METHOD
IN end of index.js file I created relations and it works as expected
db.user = require("../models/user.js")(sequelize, Sequelize);
db.tasks = require("../models/Task.js")(sequelize, Sequelize);
db.user.hasMany(db.tasks, { as: "user_tasks",foreignKey: "userId" });
db.tasks.belongsTo(db.user, {
foreignKey: "userId",
as: "task_user",
});
but when i follow the documetation i got error that i mentioned earlier
According to document
Model User.js
module.exports = (sequelize, DataTypes) => {
const User =sequelize.define('User',{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
age: {
type: DataTypes.INTEGER,
},
email: {
type: DataTypes.STRING,
},
createdAt: {
allowNull: false,
type: DataTypes.DATE
},
updatedAt: {
allowNull: false,
type: DataTypes.DATE
}
});
User.associate = (models) =>{
User.hasMany(models.Tasks, {
as: 'user_tasks',
foreignKey: 'userId'}
);
};
return User;
};
Model: Task.js
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define('Task', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
userId: {
type: DataTypes.INTEGER,
},
});
Task.associate = function(models) {
Task.belongsTo(models.User, {
as:'owner',
foreignKey:'userId',
onDelete: "cascade"
});
};
return Task;
}
This is how i am trying to get data from database
controller
const User = db.user
const {Tasks} = db.tasks
exports.usertasks = async(req,res)=>{
// const users = await User(db.sequelize,db.Sequelize).findAll({
const users = await User.findAll({
include:[{model:Tasks,as:"user_tasks"}]
});
res.json(users)
console.log("All users with their associated tasks:", JSON.stringify(users, null, 4));
}
My Index.js file
'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.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+'../models/', file))(sequelize, Sequelize.DataTypes);
console.log(model);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
//relations THIS IS WORKING AND I AM JUST CURIOUS WHETHER TO USE THIS APPROACH OR NOT
// db.user = require("../models/user.js")(sequelize, Sequelize);
// db.tasks = require("../models/Task.js")(sequelize, Sequelize);
// db.user.hasMany(db.tasks, { as: "user_tasks",foreignKey: "userId" });
// db.tasks.belongsTo(db.user, {
// foreignKey: "userId",
// as: "task_user",
// });
module.exports = db;
I am also attaching the picture of successful response that I get with the alternative method.
Kindly, guide whether the alternative method that I used is acceptable or should I stick to the documenation one?
.associate is not a native Model's method, so you need to call it manually.
I think in your index.js you want to do something like:
'use strict';
const Sequelize = require('sequelize');
const config = require('../config/config.json')[process.env.NODE_ENV || 'development'];
const requireAll = require('require-all');
const sequelize = config.use_env_variable
? new Sequelize(process.env[config.use_env_variable], config)
: new Sequelize(config.database, config.username, config.password, config);
const db = { sequelize };
const modelsInitializers = Object.values(requireAll({
dirname: __dirname,
recursive: false,
filter: (name) => name !== 'index.js' && name,
}));
const models = modelsInitializers.map((initializer) => {
const model = initializer(sequelize, Sequelize.DataTypes);
db[model.name] = model;
return model;
});
models.forEach((model) => {
if (model.associate) model.associate(db);
})
models.forEach((model) => {
if (model.associate) model.associate(models);
db[model.name] = model;
})
Object.entries().forEach(([modelName, model]) => {
model.associate(models);
db[modelName] = model;
});
module.exports = db;

Getting sequelize attribute notNull violation in my create controller due to variable name being different from column name

Im trying to add users into my database using bcrypt so I can has their passwords, but when I set the req.body to the bcrypt variable I get a notNull Violation: Users.user_password cannot be null.
This is my model I used to define my users table
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Users 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
}
};
Users.init({
user_id:{
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
user_name:{
type: DataTypes.STRING,
allowNull: false
},
user_email:{
type: DataTypes.STRING,
allowNull: false
},
user_password:{
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
timestamps: false,
modelName: 'Users',
tableName: 'users'
});
return Users;
};
This is the controller I'm using to add a new user. At the bottom when I pass in the bcryptPassword variable instead of the user_password thats deconstructed at the top, I get the notNull Violation. But if I dont pass in the bcryptPassword variable I can create a new user. Does anyone know why this is happening? Is there a way to config the model so I can use any vairable? Any help would be greatly appreciated!
Thanks!
const { Users } = require('../models');
const bcrypt = require('bcrypt');
module.exports = {
createUser: async(req, res) => {
const { user_name, user_email, user_password } = req.body;
try {
const salt = await bcrypt.genSalt(10);
const bcryptPassword = await bcrypt.hash(user_password, salt)
const newUser = await Users.create({ user_name, user_email, bcryptPassword });
return res.json(newUser);
} catch (error) {
console.error(error.message);
return res.status(500).json(error);
}
}
}
I found a viable answer while searching through the sequelize documentation.
https://sequelize.org/master/manual/getters-setters-virtuals.html
I used the set() function in my user_password field and that worked. Every time I created a new user the password was hashed in the database using bcrypt.
Here is the modified model code. Changes are marked by asterics.
'use strict';
*****const bcrypt = require('bcrypt');*****
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Users 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
}
};
Users.init({
user_id:{
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
user_name:{
type: DataTypes.STRING,
allowNull: false
},
user_email:{
type: DataTypes.STRING,
allowNull: false
},
user_password:{
type: DataTypes.STRING,
allowNull: false,
*****set(value) {
const hash = bcrypt.hashSync(value, 10);
this.setDataValue('user_password', hash);
}*****
},
}, {
sequelize,
timestamps: false,
modelName: 'Users',
tableName: 'users',
});
return Users;
};

How to fix the model.create() is not a function error in Sequelize ORM

I am new with nodejs so please go easy on me.
I am setting up a nodejs server to connect to a mysql database using Sequelize.
I currently have an error "model.create is not a function" which I cannot find any related fixes on google.
Please help me out.
Thanks in advance
This is my model.js file
const sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
const Data = sequelize.define('Data',
{
oxyVal: {
type: DataTypes.DOUBLE,
allowNull: false
},
mqState: {
type: DataTypes.BOOLEAN,
allowNull: false
},
date: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
},
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
}
});
return Data;
}
This is my index.js file
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const Sequelize = require('sequelize');
const Data = require('../models/data');
const app = express();
const port = 5500;
// I will now connect to my database
mySequelize = new Sequelize('Fast', 'root', '[password]', {
host: '127.0.0.1',
dialect: 'mysql',
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
// Test database connection here
mySequelize.authenticate().then(() => {
console.log('Database connected successfully');
}).catch((err) => {
console.error('Failed to connect to database \n ' + err);
})
app.use(morgan('dev'));
//app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser());
app.get('/');
app.post('/', (req, res, next) => {
const myData = Data.create({
oxyVal: req.body.oxyVal,
mqState: req.body.mqState,
time: req.body.time,
time: req.body.id
}).then(JSON.parse(myData)).myData.save().then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
});;
res.send('Record successfully saved');
console.log(myData);
});
app.listen(port)
console.log("Server satrted on " + port + " .....");
I was able to get your code working by doing the following 3 things:
1) rename model.js to data.js and putting it in the same directory as index.js.
2) change this:
const Data = require('../models/data');
To this:
const db = require('./data');
3) create a database 'fast', a user 'toor', with password 'password', and granted the 'toor' user full access to the 'fast' database. The connect line then ends up looking like this:
mySequelize = new Sequelize('fast', 'toor', 'password', {
Please take a look the sequelize CLI, it can help lay out your directory structure in a convenient way: http://docs.sequelizejs.com/manual/tutorial/migrations.html#the-cli

TypeError: Cannot read property 'define' of undefined

i try to change my Db from mongodb to mysql, i use sequelize instead of mongoose, and i got this error, i created the User.js model with sequelize format, but something wrong and i don't know why
const User = sequelize.define('users', {
^
TypeError: Cannot read property 'define' of undefined"
Here is my code:
server.js
const Sequelize = require('sequelize');
// DB Config
const db = require('./config/keys');
// Connect to MySql
const sequelize = new Sequelize(db.database, db.user, db.password, {
host: db.host,
dialect: 'mysql',
port: db.port
});
// Test the connection
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
const serverDB = {};
serverDB.sequelize = sequelize;
serverDB.Sequelize = Sequelize;
module.exports = serverDB;
Users.js
const serverDB = require('../server');
const sequelize = serverDB.sequelize;
const Sequelize = serverDB.Sequelize;
const User = sequelize.define('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
avatar: {
type: STRING
},
date: {
type: Sequelize.DATE,
defaudefaultValue: Sequelize.NOW
}
});
sequelize.models.modelName
// sequelize.sync()
// .then(() => {
// console.log('User db and user table have been created')
// });
module.exports = User;
You should add
const Sequelize = require('sequelize');
in your client too.
And only export and use the lowercase sequelize.
And ensure relative path of server.js is good.

Resources