Sequelize role and user relation - mysql

I am using nodejs+express, sequelize+mysql stack for RestAPI. I want to get users with it's roles table
models/user.js
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
User.belongsTo(models.Role, {
foreignKey: 'role_id',
as: 'abc'
});
}
}
User.init({
id:{
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
email: DataTypes.STRING,
password: DataTypes.STRING,
role_id: DataTypes.INTEGER,
}, {
sequelize,
modelName: 'User',
});
return User;
};
models/role.js
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Role extends Model {
Role.hasMany(models.User);
}
}
Role.init({
id:{
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
role_name: DataTypes.STRING
}, {
sequelize,
modelName: 'Role',
});
return Role;
};
controller.js
let users = await User.findAll({
include: {
model: Role,
as: 'role'
}
});
I am getting this error: TypeError: include.model.getTableName is not a function
How should i set this relation?

Related

How to exclude associated table from findAll method in sequelize JS?

I have 3 tables, course,groups and students. Each course has multiple groups and each groups have multiple students. I want to select courses and its students but when I use findAll method its displays groups too like [{courseName,courseCode,groups:[....,students:[...]]. I just want [{courseName,courseCode,students:[...]}}] .
How can i exclude group table in findAll method?
These are my tables:
Course table:
module.exports = (sequelize, DataTypes) => {
class course extends Model {
static associate(models) {
const { group } = models;
this.hasMany(group, {
foreignKey: "cid",
});
}
}
course.init(
{
cid: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
cname: DataTypes.STRING,
ccode: DataTypes.INTEGER,
},
{
indexes: [
{
unique: true,
fields: ["cname", "ccode"],
},
],
sequelize,
modelName: "course",
}
);
return course;
};
Group table:
module.exports = (sequelize, DataTypes) => {
class group extends Model {
static associate(models) {
const { teacher, studentgroup, student, subject, course } = models;
this.hasMany(subject);
this.belongsTo(course, {
onDelete: "CASCADE",
foreignKey: "cid",
});
this.belongsTo(teacher, {
onDelete: "CASCADE",
foreignKey: "tid",
});
this.belongsToMany(student, {
through: studentgroup,
foreignKey: "gid",
onDelete: "CASCADE",
});
}
}
group.init(
{
gid: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
gno: DataTypes.STRING,
},
{
sequelize,
modelName: "group",
timestamps: false,
}
);
return group;
};
Student table
module.exports = (sequelize, DataTypes) => {
class student extends Model {
static associate(models) {
const { group, studentgroup, attendance, user, studentparent, parent } =
models;
this.belongsToMany(parent, {
through: studentparent,
foreignKey: "sid",
});
this.belongsTo(user, {
foreignKey: "uid",
});
this.belongsToMany(group, {
through: studentgroup,
foreignKey: "sid",
onDelete: "CASCADE",
});
this.hasMany(attendance, {
foreignKey: "sid",
});
}
}
student.init(
{
sid: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
name: DataTypes.STRING,
lastname: DataTypes.STRING,
},
{
sequelize,
modelName: "student",
}
);
return student;
};
And this is my query:
await course.findAll({
required: true,
attributes: ["cname", "ccode"],
include: [
{
required: true,
model: models["group"],
include: [
{
model: student,
required: true,
},
],
},
],
});

this.sequelize.isDefined Node Modules?

I'm trying to seed into a database. I have successfully seeded using 2 other models, but when I try to seed data into a Model called 'Comment', I get this error:
TypeError: this.sequelize.isDefined is not a function
It has only happened for this particular model, even though the syntax is practically identical to the other two. Has anyone gotten this error before?
Here is the seed.js file. I commented out the Comment section (the one that doesn't work) but the other two are just fine.
const sequelize = require('../config/connection');
const { User, Post, Comment } = require('../models');
const userData = require('./usersSeed.json');
const postData = require('./postsSeed.json');
const commentData = require('./commentSeed.json')
const seedDatabase = async () => {
await sequelize.sync({ force: true });
await User.bulkCreate(userData, {
individualHooks: true,
returning: true,
});
await Post.bulkCreate(postData, {
individualHooks: true,
returning: true,
});
/* await Comment.bulkCreate(commentData,
{
individualHooks: true,
returning: true,
}); */
process.exit(0);
};
seedDatabase();
Here is a model that works fine
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/connection');
class Post extends Model {}
Post.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
post_title: {
type: DataTypes.TEXT,
allowNull: false
},
post_text: {
type: DataTypes.TEXT,
allowNull: true,
},
user_id: {
type: DataTypes.INTEGER,
references: {
model: 'user',
key: 'id'
}
},
date_posted: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: true,
modelName: 'post',
}
)
module.exports = Post;
Here is the Comment model
const { Model, DataTypes } = require('sequelize');
const sequelize = require('sequelize');
class Comment extends Model {}
Comment.init(
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
comment_text: {
type: DataTypes.TEXT,
allowNull: false
},
post_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'post',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id'
}
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: false,
modelName: 'comment'
}
)
module.exports = Comment;
Here is the index for the Models
const User = require('./User');
const Post = require('./Post');
const Comment = require('./Comment')
User.hasMany(Post, {
foreignKey: 'user_id'
});
Post.belongsTo(User, {
foreignKey: 'user_id',
});
Comment.belongsTo(User, {
foreignKey: 'user_id'
});
Comment.belongsTo(Post, {
foreignKey: 'post_id'
});
User.hasMany(Comment, {
foreignKey: 'user_id'
});
Post.hasMany(Comment, {
foreignKey: 'post_id'
});
module.exports = { User, Post, Comment};
Wow so dumb. I needed to change the sequelize variable to require the connection
const sequelize = require('../config/connection');

Adding Many to Many Data Sequelize

Case: I have 2 tables; one for users and one for assignments. A user can have many assignments and an assignment can be assigned to many users. I have a form in the frontend to add assignment and assign the users for the assignment and I am really confused on how to add the assignment and user to the joint table 'user_assignment'. Can someone point where I am having the mistake? Also for this, I refer to Advanced M:N Associations.
I also attach my code for the Users and Assignments model, and other relevant code parts.
user.model.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define("users", {
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
department: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.STRING,
allowNull: false,
},
});
return User;
};
assignment.model.js
module.exports = (sequelize, DataTypes) => {
const Assignment = sequelize.define("assignments", {
title: {
type: DataTypes.STRING,
allowNull: false,
},
department: {
type: DataTypes.STRING,
allowNull: false,
},
urgency: {
type: DataTypes.STRING,
allowNull: false,
},
assignmentBegin: {
type: DataTypes.STRING,
allowNull: false,
},
assignmentEnd: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING,
allowNull: false,
},
});
return Assignment;
};
database/index.js
...
db.user = require("../models/user.model")(sequelize, Sequelize);
db.assignment = require("../models/assignment.model")(sequelize, Sequelize);
...
db.user.belongsToMany(db.assignment, {
through: "user_assignment",
as: "assignments",
foreignKey: "userId",
});
db.assignment.belongsToMany(db.user, {
through: "user_assignment",
as: "users",
foreginKey: "assignmentId",
});
...
assignment.controller.js
const db = require("../database");
const Assignment = db.assignment;
const User = db.user;
exports.create = async (req, res) => {
const {
participant,
title,
department,
urgency,
assignmentBegin,
assignmentEnd,
description,
} = req.body;
await Assignment.create({
title: title,
department: department,
urgency: urgency,
assignmentBegin: assignmentBegin,
assignmentEnd: assignmentEnd,
description: description
}).then(async result => {
for (i = 0; i < participant.length; i++) {
const user = await User.findByPk(participant[i])
// console.log(user.id)
await UserController.addAssignment(user.id, result.id);
// await UserController.addAssignment(2, 1)
}
}).catch(err => {
res.json({ message: "ERROR WHILE CREATING ASSIGNMENT!" });
console.log(">>> ERROR WHILE CREATING ASSIGNMENT!")
});
}
Any pointers on what I should do would be great!
I'd recommend you define the model associations inside each of the model files. Also you should hash/encrypt your passwords before saving them to the DB, you can use the .comparePassword() function outside of the model in a controller when logging in etc.
models/User.js
const Promise = require('bluebird')
const bcrypt = Promise.promisifyAll(require('bcrypt'))
function hashPassword (user) {
const SALT_FACTOR = 12
if (!user.changed('password')) {
return;
} else {
user.setDataValue('password', bcrypt.hashSync(user.password, SALT_FACTOR))
}
}
module.exports = User = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
department: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.STRING,
allowNull: false,
},
{
hooks: {
beforeCreate: hashPassword,
beforeUpdate: hashPassword
}
})
User.associate = models => {
User."Association type here"(models."Model to associate",
{Options (For many to many add your "through" table here)}
)
// Example:
User.belongsToMany(models.Assignment, {
through: "UserAssignment"
})
}
User.prototype.comparePassword = function (password) {
return bcrypt.compareSync(password, this.password)
}
return User
}
And in the associated Model (models/Assignment.js):
module.exports = Assignment = (sequelize, DataTypes) => {
const Assignment = sequelize.define('Assignment', {
title: {
type: DataTypes.STRING,
allowNull: false,
},
department: {
type: DataTypes.STRING,
allowNull: false,
},
urgency: {
type: DataTypes.STRING,
allowNull: false,
},
assignmentBegin: {
type: DataTypes.STRING,
allowNull: false,
},
assignmentEnd: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
timestamps: false
})
Assignment.associate = models => {
Assignment.belongsToMany(models.User, {
through: "UserAssignment"
})
}
return Role
}
The joint table (models/UserAssignment.js):
module.exports = UserAssignment = (sequelize, DataTypes) => {
const UserAssignment = sequelize.define('UserAssignment', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
}
},
{
timestamps: false
})
return UserAssignment
}
And finally my index.js file (models/index.js), it programatically adds the models to the DB:
'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, 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;
As an extra note, you can shorten down your createAssignment function in your controller by doing this instead:
const {
participant,
title,
department,
urgency,
assignmentBegin,
assignmentEnd,
description,
} = req.body;
await Assignment.create({
title: title,
department: department,
urgency: urgency,
assignmentBegin: assignmentBegin,
assignmentEnd: assignmentEnd,
description: description
}).then(async result => {
result.addUsers(participant)
}).catch(err => {
res.json({ message: "ERROR WHILE CREATING ASSIGNMENT!" });
console.log(">>> ERROR WHILE CREATING ASSIGNMENT!")
});
Hope this helps, if not lmk ill try to help some more.

Sequelize Error: you must use the 'as' keyword to specify the alias of the association you want to include. - node.js

I am making a web application which is similar to 'Twitter'.
When I ran the server,
'user is associated to user multiple times. To identify the correct association,
You must use the 'as' keyword to specify the alias of the association you want to include.'
<- this message appeared.
I applied 'as' keyword for the relationship between 'followers' and 'followings'.
but the error message kept on appearing.
I'm sure that I did something wrong in someway, but I can't figure out what exactly it is.
can somebody help me?
models/index.js
'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, 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;
db.User = require('./user')(sequelize, Sequelize);
db.Post = require('./post')(sequelize, Sequelize);
db.Hashtag = require('./hashtag')(sequelize, Sequelize);
db.User.hasMany(db.Post); //1 : n
db.Post.belongsTo(db.User);
// m: n
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
// I use alias here *****
db.User.belongsToMany(db.User, {
foreignKey: 'followingId',
as: 'Followers',
through: 'Follow',
});
db.User.belongsToMany(db.User, {
foreignKey: 'followerId',
as: 'Followings',
through: 'Follow',
});
module.exports = db;
models/user.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('user', {
email: {
type: DataTypes.STRING(40),
allowNull: true,
unique: true,
},
nick: {
type: DataTypes.STRING(15),
allowNull: false,
},
password: {
type: DataTypes.STRING(100),
allowNull: true,
},
provider: {
type: DataTypes.STRING(10),
allowNull: false,
defaultValue: 'local',
},
snsId: {
type: DataTypes.STRING(30),
allowNull: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
models/post.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('user', {
email: {
type: DataTypes.STRING(40),
allowNull: true,
unique: true,
},
nick: {
type: DataTypes.STRING(15),
allowNull: false,
},
password: {
type: DataTypes.STRING(100),
allowNull: true,
},
provider: {
type: DataTypes.STRING(10),
allowNull: false,
defaultValue: 'local',
},
snsId: {
type: DataTypes.STRING(30),
allowNull: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
models/hashtag.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('hashtag', {
title: {
type: DataTypes.STRING(15),
allowNull: false,
unique: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
I think this will solve your problem you have to create a table follower than associate it with user table with following and follower alias and use it to query follower and following
follower Model
module.exports = (sequelize, datatypes) => {
sequelize.define('follower', {
_id: {
type: datatypes.integer,
allownull: false,
primarykey: true,
autoincrement: true
},
userid: {
type: datatypes.integer,
allownull: false
},
followingid: {
type: datatypes.integer,
allownull: false
}
});
}
association
db.follower.belongsTo(db.user, {
as: 'following',
foreignkey: 'followingid'
});
db.follower.belongsto(db.user, {
as: 'follower',
foreignkey: 'userid'
});
query to get follower
follower.findall({
where: {
followingid: userid
},
attributes: ['_id'],
include: [{
model: user, attributes:
['fullname', 'username', '_id', 'picture'],
as: 'follower'
}]
})

Association in Sequelize throwing error as <model1> not connected to <model2>

I am new to the database and learning sequelize (Postgres). I am building a blogging web app and trying to implement association in my DB but getting a server-side error as
error: creator is not associated with blogpost
here is what I have done till now.
creator_model
const Sequelize = require('sequelize');
const db = require('../db/dbConfig');
const bcrypt = require('bcrypt');
const Creator = db.sequelize.define('creator', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false
}
},
{
hooks: {
beforeCreate: (Creator) => {
Creator.password = bcrypt.hashSync(Creator.password,10)
}
}
}
);
Creator.associate = (models) => {
console.log('visited here')
Creator.hasMany(models.BlogPost,{
foreignKey: "creatorId",
as: "owner",
onDelete: 'CASCADE'
});
}
module.exports = Creator;
Blog_model
const Sequelize = require('sequelize');
const Creator = require('../models/CreatorModel');
const db = require('../db/dbConfig');
const BlogPost = db.sequelize.define('blogpost',{
blogId: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
title: {
type: Sequelize.STRING,
allowNull: false
},
cover: {
type: Sequelize.STRING,
allowNull: false
},
body: {
type: Sequelize.TEXT,
allowNull: false
},
creatorId: {
type: Sequelize.INTEGER,
references:{
model: Creator,
key: 'id'
},
allowNull: false
},
likes: {
type: Sequelize.INTEGER,
defaultValue: 0
}
},{});
BlogPost.associate = (models) => {
BlogPost.hasMany(models.Comment,{
foreignKey: 'postId',
as: 'blogpost',
onDelete: 'CASCADE'
});
BlogPost.belongsTo(models.Creator,{
foreignKey: 'creatorId',
as: 'creator',
onDelete: 'CASCADE'
})
}
module.exports = BlogPost;
Comment_model
const Sequelize = require('sequelize');
const BlogPost = require('../models/BlogPostModel');
const db = require('../db/dbConfig');
const Comment = db.sequelize.define('comment',{
commentId: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
name: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
message: {
type: Sequelize.TEXT,
allowNull: false
},
blogPostId: {
type: Sequelize.INTEGER,
references: {
model: BlogPost,
key: 'blogId'
},
allowNull: false
}
},{});
Comment.associate = (models) => {
Comment.belongsTo(models.BlogPost,{
foreignKey: 'blogPostId',
as: 'blog',
onDelete: 'CASCADE'
})
}
module.exports = Comment;
here is my DB config with express and sequelize
const Sequelize = require('sequelize');
const dotenv=require("dotenv");
dotenv.config();
const db ={}
const sequelize = new Sequelize(`${process.env.DB_NAME}`, `${process.env.DB_USERNAME}`, `${process.env.DB_PASSWORD}`, {
host: 'localhost',
dialect: 'postgres'
})
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
db.sequelize = sequelize
db.Sequelize = Sequelize
sequelize.sync()
.then(() => {
console.log(`Database & tables created!`)
})
.catch(error => console.log("DB error: ",error));
module.exports = db;
controller.js
const BlogPost = require('../models/BlogPostModel');
const Comment = require('../models/CommentModel');
const Creator = require('../models/CreatorModel');
const getAllBlog = (req,res) =>{
BlogPost.findAll({
include: [
{
model: Creator,
as: "author",
include: [{
model: Comment,
as: "comments"
}]
}
]
})
.then(data => {
res.json(data)
})
.catch(error => {
res.status(500).json({error: error.message})
})
}
module.exports = {
getAllBlog
}