sequelize association N:M Table and 1:N Table - node.js

I am using sequelize, mysql for node.js!
Have a question and post it.
First, to create a review table with N: M relationship between user table and store table!
Please refer to the ReviewImage Table, which is a 1: N relationship with the Review Table.
For synchronization, please refer to the Review Table and ReviewImage Table.
I don't know what the problem is even if I browse the sequelize API documentation!
Have you ever done the wrong database design?
Should I design a review image table?
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(
config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = require('./UserModel')(sequelize, Sequelize);
db.Store = require('./StoreModel')(sequelize, Sequelize);
db.Review = require('./reviewModel')(sequelize, Sequelize);
db.ImageReview = require('./imageReviewModel')(sequelize, Sequelize);
/** N:M User : Store (Review) */
db.User.belongsToMany(db.Store, { through: db.Review});
db.Store.belongsToMany(db.User, { through: db.Review});
/** 1:N review : imageReview */
db.Review.hasMany(db.ImageReview);
db.ImageReview.belongsTo(db.Review);
module.exports = db;
// userModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('User',{
userPlatformType:{
type: DataTypes.STRING(50),
},
userNickname:{
type: DataTypes.STRING(50),
allowNull: false,
unique : true,
},
customerEmail: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
userPassword:{
type: DataTypes.STRING(200),
allowNull: false,
},
salt:{
type: DataTypes.STRING(200),
},
userPhoneNumber:{
type: DataTypes.STRING(45),
},
userDateOfBirth:{
type: DataTypes.DATEONLY,
},
userWeddingDay:{
type: DataTypes.DATEONLY,
},
userProfile: {
type: DataTypes.STRING(200),
allowNull: true,
},
}, {
freezeTableName: true,
});
};
// storeModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('Store',{
storeName:{
type: DataTypes.STRING(50),
},
storeCategory: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
storeAddress:{
type: DataTypes.STRING(150),
allowNull: false,
unique : true,
},
storeLatitude:{
type: DataTypes.STRING(45),
},
storeLongtitude:{
type: DataTypes.STRING(45),
},
storeCondition: {
type: DataTypes.STRING(200),
allowNull: false,
},
storePhoneNumber:{
type: DataTypes.STRING(200),
allowNull: false,
},
storeProfile:{
type: DataTypes.STRING(200),
},
storeWifi:{
type: DataTypes.STRING(45),
},
storePost:{
type: DataTypes.STRING(100),
},
storeItem:{
type: DataTypes.STRING(100),
},
storeIntro:{
type: DataTypes.STRING(100),
},
storeLike: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
storeRating: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
storeIsJoin: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
}, {
freezeTableName: true,
});
};
//ReviewModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('Review',{
reviewWriter :{
type: DataTypes.STRING(50),
allowNull: false,
},
reviewContent :{
type: DataTypes.STRING(200),
allowNull: false,
},
reviewGrade : {
type: DataTypes.INTEGER,
allowNull: false,
},
reviewIsDeclare : {
type: DataTypes.BOOLEAN,
allowNull: false,
},
}, {
freezeTableName: true,
});
};
//ReviewImage.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('ImageReview',{
reviewImageUrl :{
type: DataTypes.STRING(200),
allowNull: false,
},
}, {
freezeTableName: true,
});
};

Related

Get data from multiple tables using Seqeulize

I have two tables, Post and Comments, I am trying to get all posts by userId and also fetch the relevant comments for each post using the following code. I am getting all the posts but nodejs through an error " comment is not associated to post".
Post Table
const {Sequelize, DataTypes} = require('sequelize')
const db = require('../config/db')
const Post = db.define('post', {
id:{
type: DataTypes.INTEGER(255),
autoIncrement: true,
allowNull: false,
primaryKey: true
},
postId:{
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4
},
postText:{
type: DataTypes.TEXT,
allowNull: false
},
totalPostLikes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
totalPostStrikes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
totalPostQuotes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
totalPostShare: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
userId:{
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
},{
freezeTableName: true
})
module.exports = Post
Comments Table
const {Sequelize, DataTypes} = require('sequelize')
const db = require('../config/db')
const Comment = db.define('comment', {
id:{
type: DataTypes.INTEGER(255),
autoIncrement: true,
allowNull: false,
primaryKey: true
},
commentUUID:{
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4
},
commentText:{
type: DataTypes.TEXT,
allowNull: false
},
totalCommentLikes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
totalCommentStrikes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
totalCommentQuotes: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
},
userId:{
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}, postId:{
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'post',
key: 'id'
}
}
},{
freezeTableName: true
})
module.exports = Comment
This is how I am creating tables and associations
const db = require('../config/db')
const User = require('./user')
const Post = require('./posts')
const Comments = require('./comments')
User.hasMany(Post)
Post.belongsTo(User)
Post.hasMany(Comments)
Comments.belongsTo(Post)
User.hasMany(Comments)
Comments.belongsTo(User)
db.sync({force: true})
.then((result) =>{
console.log(result)
})
.catch((error) => {
console.log(error)
})
Code to fetch data
router.get('/:id', authenticate, async (req,res) => {
const { id } = req.params
const data = await Post.findAll(
{where: {userId: id},
attributes: [
'postText',
'totalPostLikes',
'totalPostStrikes',
'totalPostQuotes',
'totalPostShare'
],
include:[{model: Comments, attributes:['commentText']}]
})
try{
res.send(data);
} catch({errors}) {
res.status(400).send(errors)
}
})
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const db = require('../models');
var main = async () => {
try {
const data = await db.post.findAll({
where: { userId: 1 },
attributes: ['postText', 'totalPostLikes', 'totalPostStrikes', 'totalPostQuotes', 'totalPostShare'],
include: [{ model: db.comment, attributes: ['commentText'], as: 'comments' }],
});
console.log(JSON.parse(JSON.stringify(data)));
} catch (e) {
console.log(e);
}
};
main();

How to make sequelize model seperate file but same sequelize connection

everyone. I'm very new for sequelize ORM with nodejs.
I've just created couple files for models seperately and I also seperate sequelize.js to connect to database.
The problem is when I make association between model(file)(Self Associate work well) and I've got an error
**** "hasMany called with something that's not a subclass of Sequelize.Model"
I tried to solved this but doesn't work until I put every model in the same file. So, I realized that every model must use common sequelize connection.
Is there anyways to solve this problem without sequelize-cli (I don't want to use sequelize-cli)
My code belows
Many thanks,
sequelize.js
const config = require("config");
const { Sequelize } = require("sequelize");
const sequelize = new Sequelize(
config.get("database"),
config.get("user"),
config.get("cipher"),
{
dialect: "mariadb",
timezone: "Asia/Bangkok",
}
);
module.exports = sequelize;
user.js
const { DataTypes, Model } = require("sequelize");
const sequelize = require("./sequelize");
const Position = require("./position");
class User extends Model {}
User.init(
{
uuid: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
firstname: {
type: DataTypes.STRING,
allowNull: false,
},
lastname: {
type: DataTypes.STRING,
allowNull: false,
},
phone: {
type: DataTypes.STRING,
allowNull: true,
},
email: {
type: DataTypes.STRING,
allowNull: true,
validate: {
isEmail: true,
},
},
imgurl: {
type: DataTypes.STRING,
allowNull: true,
},
login: {
type: DataTypes.STRING,
allowNull: false,
},
passphase: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
},
},
{
sequelize,
modelName: "User",
tableName: "users",
timestamps: true,
}
);
User.belongsToMany(User, {
as: "CreatedUser",
foreignKey: "user_id",
through: "UserCreator",
});
User.belongsToMany(User, {
as: "Creator",
foreignKey: "creator_id",
through: "UserCreator",
});
User.belongsToMany(User, {
as: "ModifiedUser",
foreignKey: "user_id",
through: "UserModifier",
});
User.belongsToMany(User, {
as: "Modifier",
foreignKey: "modifier_id",
through: "UserModifier",
});
User.belongsTo(Position);
module.exports = User;
position.js
const { DataTypes, Model } = require("sequelize");
const sequelize = require("./sequelize");
const User = require("./user");
class Position extends Model {}
Position.init(
{
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
},
},
{
sequelize,
modelName: "Position",
tableName: "postions",
timestamps: true,
}
);
Position.hasMany(User, {
foreignKey: {
type: DataTypes.UUIDV4,
allowNull: false,
},
});
module.exports = Position;
Sequelize has a .define() method to create all your schemas in JSON. If you want to keep your connection to the database separate from your models, I suggest doing something like this
./models/schemas/User.js
const userSchema = {
attribute1: {
type: ...,
option1: ...,
option2: ...,
.
.
},
.
.
}
export default userSchema
Do the same with Position.js
Then:
./models/models.js
import {sequelize} from 'path/to/sequelize.js'
import positionSchema from './schemas/Position.js'
import userSchema from './schemas/User.js'
const User = sequelize.define("user", userSchema, { freezeTableName: true });
const Position = sequelize.define("position", positionSchema, { freezeTableName: true });
// add associations
export {
User,
Position,
.
.
}

Why does associating belongsTo in Sequelize give me this error?

I'm stuck with this problem for quite some time now and I don't know what's wrong with my code I'm trying to associate one table to another but only half of it works any help would be greatly appreciated.
models/companies.js
const DataTypes = require('sequelize');
const sequelize = require('../config/database');
const Users = require('./users');
const Companies = sequelize.define(
'companies',
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING(50),
unique: true,
allowNull: false
},
image_url: {
type: DataTypes.STRING(100),
unique: true
},
created_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
},
updated_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
}
},
{
//Rewrite default behavior of sequelize
timestamps: false,
paranoid: true,
underscored: true
}
);
Companies.hasMany(Users);
Users.belongsTo(Companies);
Companies.sync();
module.exports = Companies;
models/users.js
const DataTypes = require('sequelize');
const sequelize = require('../config/database');
const Users = sequelize.define(
'users',
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING(40),
allowNull: false
},
email: {
type: DataTypes.STRING(60),
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING(60)
},
role: {
type: DataTypes.STRING(40),
allowNull: false
},
image_url: {
type: DataTypes.STRING(100),
unique: true
},
batch: {
type: DataTypes.STRING(3)
},
major: {
type: DataTypes.STRING(10)
},
company_id: {
type: DataTypes.INTEGER,
allowNull: false
},
created_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
},
updated_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
}
},
{
//Rewrite default behavior of sequelize
timestamps: false,
paranoid: true,
underscored: true
}
);
Users.sync();
module.exports = Users;
Then after I try to run this code below
const Companies = require('./database/models/companies');
const Users = require('./database/models/Users');
//Relation 1: Company and Users
Companies.findAll({ include: [ Users ] }).then((res) => console.log(res));
Users.findAll({ include: [ Companies ] }).then((res) => console.log(res));
it gives me this error:
(node:4893) UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: companies is not associated to users!
I've tried a couple of solutions online but it didn't help in this case.
BelongsTo means one to one relationship while a company may have multiple users (meaning, calling BelongsTo after hasMany collide!).
For more: https://sequelize.org/master/manual/assocs.html

Cannot read property 'menu_id' of undefined

I tried to create database with 3 tables: restaurant,restaurant_menu,menu and their relationship is restaurant have many menu and menu can belong to many restarant by sequelize in Nodejs.
restaurant.model.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const restaurant = sequelize.define('restaurant', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
name: DataTypes.STRING,
address: DataTypes.STRING,
phone: DataTypes.STRING,
lat: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: 0
},
lng: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: 0
},
user_owner: {
type: DataTypes.INTEGER,
defaultValue: 0
},
image: {
type: DataTypes.TEXT,
allowNull: false
},
payment_url: {
type: DataTypes.TEXT,
allowNull: false
}
}, {
freezeTableName: true,
timestamps: false
});
restaurant.associate = function (models) {
// associations can be defined here
restaurant.belongsToMany(models.menu, {
through: {
model: models.restaurant_menu
},
foreignKey: 'restaurant_id'
})
};
return restaurant;
};
menu.model.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const menu = sequelize.define('menu', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false
},
name: DataTypes.STRING(50),
description: DataTypes.STRING(500),
image: DataTypes.TEXT
}, {
freezeTableName: true,
timestamps: false
});
menu.associate = function (models) {
// associations can be defined here
menu.belongsToMany(models.restaurant, {
through: {
model: models.restaurant_menu
},
foreignKey: "menu_id"
});
};
return menu;
};
restaurant_menu.model.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const restarant_menu = sequelize.define('restarant_menu', {
restaurant_id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
references: {
model: 'restaurant'
}
},
menu_id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
references: {
model: 'menu'
}
}
}, {
freezeTableName: true,
timestamps: false
});
restarant_menu.associate = function (models) {
// associations can be defined here
};
return restarant_menu;
};
i tried to run migration, but i get error:
Cannot read property 'menu_id' of undefined
How can I fix it?
I believe you are writing old syntax, checkout documentation.
https://sequelize.org/master/manual/advanced-many-to-many.html

How to associated two models in node JS

I'm trying to make this connection between these two tables, but I'm not getting it and it's giving the following error: "UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: cfg_user is not associated to dn_coluna!"
follows below the controllers and models that I am using to inner join
This is my cfg_user.js
const sequelizePaginate = require("sequelize-paginate");
module.exports = function(sequelize, DataTypes) {
const cfg_user = sequelize.define("cfg_user", {
'id_cfg_user': {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
'id_cfg_grupo': {
type: DataTypes.INTEGER(11),
allowNull: true
},
'nome': {
type: DataTypes.CHAR(100),
allowNull: true
},
'email': {
type: DataTypes.CHAR(100),
allowNull: true
},
'arquivo': {
type: DataTypes.CHAR(255),
allowNull: false
},
'senha': {
type: DataTypes.CHAR(32),
allowNull: true
}
},{
tableName: "cfg_user",
freezeTableName: true,
timestamps: false
});
sequelizePaginate.paginate(cfg_user);
return cfg_user;
};
This is my dn_coluna.js
const sequelizePaginate = require("sequelize-paginate");
const cfg_user = require("./cfg_user");
module.exports = function(sequelize, DataTypes) {
const dn_coluna = sequelize.define("dn_coluna", {
'id_dn_coluna': {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
'id_cfg_user': {
type: DataTypes.INTEGER(10),
allowNull: false
},
'coluna': {
type: DataTypes.CHAR(255),
allowNull: false
},
'frase': {
type: DataTypes.CHAR(255),
allowNull: true,
},
'resumo': {
type: DataTypes.CHAR(255),
allowNull: true,
},
'url': {
type: DataTypes.CHAR(255),
allowNull: true
},
'arquivo': {
type: DataTypes.CHAR(255),
allowNull: true
},
'arquivo_topo': {
type: DataTypes.CHAR(255),
allowNull: true
},
'arquivo_bg': {
type: DataTypes.CHAR(255),
allowNull: true
},
'ordem': {
type: DataTypes.INTEGER(11),
allowNull: true
},
'destaque':{
type: DataTypes.TINYINT(1),
allowNull: true
},
'libera': {
type: DataTypes.TINYINT(1),
allowNull: true
}
},{
tableName: "dn_coluna",
freezeTableName: true,
timestamps: false
});
sequelizePaginate.paginate(dn_coluna);
return dn_coluna;
};
this is my Controller
const { dn_coluna } = require("../models");
const { cfg_user } = require("../models");
module.exports = {
async index(req, res){
const colunas = await dn_coluna.findAll({
include: [{
model: cfg_user,
attributes: []
}],
attributes: ['id_cfg_user'],
})
.then(colunas => {
return res.status(200).json(colunas);
});
},
};
Your answer lies in associations. You are not properly associating your tables together. Here is a link to the documentation. I am unsure of the type of relationship that cfg_user and dn_coluna have so I can't show you how to write the association but the below may help.
Remove the below from dn_coluna.js
'id_cfg_user': {
type: DataTypes.INTEGER(10),
allowNull: false
}
Add in to dn_coluna.js (just above sequelizePaginate.paginate(dn_coluna);):
dn_coluna.associate = (models) => {
dn_coluna.hasMany(models.cfg_user, {foreignKey: 'cfg_user_id'})
}
In cfg_user.js add (just above sequelizePaginate.paginate(cfg_user);):
cfg_user.associate = (models) => {
cfg_user.belongsTo(models.dn_coluna)
}
The above will create a one to many relationship between dn_coluna and cfg_user.

Resources