Sequelize assocation functions have no effect - javascript

I use the present Sequelize version and try to build the associations between two models. Should be actually pretty simple since Sequelize offers hasMany and belongsTo.
But the call has no effect at all. I tried it with a new SQL DB. The tables itself are created, just without any foreign key.
db controller
const userModel = require('../model/user')
const subjectModel = require('../model/subject')
const database = require('../db/database').sequeliceInstance
async function setupAssociations () {
await database.sync()
// user + subject
userModel.hasMany(subjectModel)
subjectModel.belongsTo(userModel)
// subject and topic
subjectModel.hasMany(topicModel)
topicModel.belongsTo(subjectModel)
// topic and question
topicModel.hasMany(questionModel)
questionModel.belongsTo(topicModel)
// question and answer
questionModel.hasMany(answerModel)
answerModel.belongsTo(questionModel)
return Promise.resolve()
}
user.js
const Sequelize = require('sequelize')
const db = require('../db/database').sequeliceInstance
const user = db.define('user', {
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
title: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.TEXT,
allowNull: false
}
})
module.exports = user
subject.js
const Sequelize = require('sequelize')
const db = require('../db/database').sequeliceInstance
const subject = db.define('subject', {
// attributes
subjectName: {
type: Sequelize.TEXT,
allowNull: false
}
})
module.exports = subject

I found the solution.
await database.sync() has to be called at the very end of the function.

Related

How to create model with association M-N via Sequelize

Stack: NodeJs, PostgreSQL, Sequelize, Express.
I have two associated models (User and Role) through User_Roles.
When I create new user via Sequelize.create(), how can i fill the User_Roles table to define which roles (i get the array filled with role ID) the user have. The roles are already defined in table (roles)
The models:
const User = sequelize.define('users', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
email: { type: DataTypes.STRING(320), allowNull: false, unique: true, isEmail: true },
});
const Role = sequelize.define('roles', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
title: { type: DataTypes.STRING(64), allowNull: false, unique: true },
});
const User_Roles = sequelize.define('user_roles', {}, { timestamps: false });
// Associations
User.belongsToMany(Role, { through: User_Roles });
Role.belongsToMany(User, { through: User_Roles });
UserController:
async create(req, res, next) {
const { email, roles } = req.body;
if (!email) {
return next(ApiError.badRequest('Invalid request'));
}
if (!Array.isArray(roles) || !roles.length) {
return next(ApiError.badRequest('Invalid request'));
}
const isExistThisEmail = await User.findOne({ where: { email } });
if (isExistThisEmail) {
return next(ApiError.badRequest('The email already exists'));
}
const user = await User.create({ email });
return res.status(201).json(createdUser);
}
You can use dynamically added methods (according to associations) in the model:
await user.setRoles([1,2,3]) // or indicate the roles instances
See special methods/mixins

SQLite says table doesn't exist when I created it with Sequelize

I'm trying to understand how Sequelize works and I don't understand why I get SQLITE_ERROR: no such table: Users even though I created the table with sequelize.define. Code:
const { Sequelize, DataTypes } = require('sequelize');
const db = new Sequelize({
dialect: 'sqlite',
storage: './database.sqlite',
});
async function testdb() {
try {
await db.authenticate();
console.log('db connected'); // test 1
} catch (error) {
console.error(error);
}
const User = db.define('User', {
userName: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
bio: {
type: DataTypes.TEXT,
},
});
console.log(db.models.User); // test 2
const user = await User.create({
userName: 'epic_user01',
email: 'epic.user#gmail.com',
bio: 'hello world!!!',
});
console.log(user.id); // test 3
}
testdb();
Tests 1 and 2 return successful before I get the error message.
You have to call sync to actually create the tables, add this right after the define and before the create:
await User.sync();

problems to update mongodb collection

so I have two different collections for my social media app. One for the users and the other one for the user's posts. Whenever I'm updating the info from one of my user's collection it should also modify it on the post (since my post collection includes data from the user too), but it's only doing it on the posts that I create after that and not on the ones that I've been creating before. How can I fix it?
USER SCHEMA
const userSchema = new Schema({
name: { type: String, required: true },
lastname: { type: String, required: true },
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true, minlength: 8 },
avatar: { data: Buffer, contentType: String },
});
POST SCHEMA
const postSchema = new Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
name: { type: String, required: true },
lastname: { type: String },
username: { type: String },
avatar: { data: Buffer, contentType: String },
date: { type: Date, default: Date.now() },
textOfThePost: { type: String, required: true },
});
EDIT FUNCTION EXPRESS/MONGOOSE
router.put("/edit_profile", async (req, res) => {
try {
const { name, lastname, username } = req.body;
const user = await User.findById(req.user).select("-password");
if (!user) return res.status(404).json("User doesn't exists");
if (name) user.name = name;
if (lastname) user.lastname = lastname;
if (username) user.username = username;
await user.save();
res.json(user);
} catch (err) {
res.status(500).json({ error: err.message });
}
};
You can use updateMany() for that purpose.
const res = await Post.updateMany({ user: user.id }, { name: user.name, username: user.username /* ... */ });
However as already pointed out you are storing user data redundant on the post model as well as on the user model which is not necessary. Similar to joins in SQL you can simply use populate() and not store any user-related data on your post model. This way everytime you query your posts it will automatically pull the latest matching user model by its id.
myPost.populate('user')
Note that therefore the ref is required, which tells mongoose how to populate the user field.

Model not getting imported as a Sequelize.Model

I'm trying to use a sequelize N:M relation trough another table but I keep getting this error:
throw new Error(${this.name}.belongsToMany called with something that's not a subclass of Sequelize.Model);
Error: Cases.belongsToMany called with something that's not a subclass of Sequelize.Model
Here are my classes:
models/User.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const DocumentType = require('./DocumentType');
const Case = require('./Case');
const User = sql.define('Users', {
firstName: Sequelize.STRING,
lastName: Sequelize.STRING,
email: Sequelize.STRING,
document: Sequelize.INTEGER,
documentTypeId: Sequelize.INTEGER,
password: Sequelize.STRING,
active: Sequelize.INTEGER
});
User.belongsTo(DocumentType, {foreignKey: 'documentTypeId' ,as: 'documentType'});
User.belongsToMany(Case, { through: 'CaseUser' });
User.findById = (id) => {
return User.findOne({
where: {
id: id
},
include: 'documentType'
});
};
User.findByEmail = (email) => {
return User.findOne({
where: {
email: email
},
include: 'documentType'
});
};
User.checkActiveStatus = (id) => {
return User.findOne({
where: {
id: id
},
attributes: ['active']
});
};
module.exports = User;
models/Case.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const User = require('./User');
const Case = sql.define('Cases', {
description: Sequelize.STRING,
startDate: Sequelize.STRING
});
Case.belongsToMany(User, {through: 'CaseUser'});
module.exports = Case;
I get the error only in the Case.belongsToMany(User, { through: 'CaseUser' }); and not in the User.belongsToMany(Case, { through: 'CaseUser' }); one
The weird thing is that if I switch the belongsToMany(User... for belongsToMany(DocumentType... and import the DocumentType file I don't get the error. The DocumentType Model is virtually identical to the User one
models/DocumentType.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const DocumentType = sql.define('DocumentTypes', {
name: Sequelize.STRING,
slug: Sequelize.STRING
}, {
timestamps: false
});
module.exports = DocumentType;
Any ideas on what could be causing this behavior?
Thanks!
You should try to avoid circular dependencies.
Remove lines
const Case = require('./Case');
and
Case.belongsToMany(User, {through: 'CaseUser'});
from User.js
Remove lines
const User = require('./User');
and
User.belongsToMany(Case, { through: 'CaseUser' });
from Case.js
Create associations.js
const Case = require('./Case');
const User = require('./User');
Case.belongsToMany(User, {through: 'CaseUser'});
User.belongsToMany(Case, { through: 'CaseUser' });

I can not create a "researcher" using the sequelize

I try to create a new researcher but I just go into catch, and I do not get any errors. I am new using sequelize, I need a lot of help for this problem, my complete code in git: https://github.com/chanudinho/RevYou-BackEnd.
I can't explain it better, please if you need to download the project and test it. Sorry for my english =x
researcherController.js
const Researcher = require('../../sequelize/models/researcher');
const createResearcher= async (req, res) => {
try{
Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso');
}catch (err){
return res.status(500).send('error');
}
}
models/researcher.js
module.exports = (sequelize, DataTypes) => {
const Researcher = sequelize.define('Researcher', {
name: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING
});
return Researcher;
};
migrations/20190114200431-create-researcher
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Researcher', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
allowNull: false,
type: Sequelize.STRING
},
email: {
allowNull: false,
type: Sequelize.STRING
},
password:{
allowNull: false,
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Researcher');
}
};
models/index.js
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const config = require('../../config/database.js');
const db = {};
const sequelize = new Sequelize(config);
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
.forEach((file) => {
const 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;
The problem is that you are importing the model file and this is not right, your index.js within model maps all model files by adding the sequelize instance and the datatypes. You should always import the index.
If you import the model index and give a console.log() in it will see that you have the object of your model and the instance of the sequelize.
const db = require('../../sequelize/models/index');
console.log(db)
Inside the exit will have something like this: Example:
Researcher: Researcher,
sequelize:
Sequelize { ....
To access your model you can do the following. By using destructuring assignment, you extract the model from within the index.
Result
const { Researcher } = require('../../sequelize/models/index')
const createResearcher= async (req, res) => {
try{
await Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso')
}catch (err){
return res.status(500).send('error');
}
}
Whenever you create a new file inside the model folder, it will be mapped by index.js and added inside the matrix and using destructuring you can access or use the matrix key itself.
const db = require('../../sequelize/models/index')
const createResearcher= async (req, res) => {
try{
await db.Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso')
}catch (err){
return res.status(500).send('error');
}
}

Categories

Resources