Sequelize Node.js Model not associated to model - node.js

I have two models in my Node JS application, Users and Companies. When I try to use the include function when getting the companies, I get the error:
message: "users is not associated to companies!"
This is the user model
import { Sequelize, DataTypes } from 'sequelize';
import { Application } from '../declarations';
export default function (app: Application) {
const sequelizeClient: Sequelize = app.get('sequelizeClient');
const users = sequelizeClient.define('users', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: true
},
role: {
type: DataTypes.STRING,
allowNull: true,
},
language: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'en',
},
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
}, {
underscored: true,
hooks: {
beforeCount(options: any) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
(users as any).associate = function (models: any) {
(users as any).belongsTo(models.companies, {
foreignKey: 'companyId',
allowNull: true,
onDelete: "CASCADE",
});
};
return users;
}
and the companies model:
import { Sequelize, DataTypes, Model } from 'sequelize';
import { Application } from '../declarations';
export default function (app: Application) {
const sequelizeClient: Sequelize = app.get('sequelizeClient');
const companies = sequelizeClient.define('companies', {
name: {
type: DataTypes.STRING,
allowNull: false
},
phone: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
},
email: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
},
active: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
}, {
underscored: true,
hooks: {
beforeCount(options: any) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
(companies as any).associate = function (models: any) {
(companies as any).hasMany(models.users);
(companies as any).hasMany(models.patients);
};
return companies;
}
And the include function
function getSuperAdmin() {
return (context: HookContext) => {
const sequelizeClient = context.app.get("sequelizeClient");
context.params.sequelize = {
include: [
{
model: sequelizeClient.models.users,
as: 'users',
required: false,
where: {
'$users.role$': 'super_admin'
}
}
],
};
return context;
}
}
When I include the companies model in the user query, it works correctly. But not the other way around. Any ideas?
Thanks

Related

Sequelize ts: How to set foreign key value

I need that when registering the user, the account should also be created automatically and I managed to do this using sequelize hooks, but the accountId I am not able to insert its value automatically and it always has a null value, I need that when the accountId has the id of Account, but I don't know how to do that
My models
import { Model, DECIMAL, INTEGER } from 'sequelize';
import db from '.';
class Account extends Model {
id!: number;
balance!: number;
};
Account.init({
id: {
type: INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
balance: {
type: DECIMAL(13, 2),
allowNull: false
},
},
{
sequelize: db,
modelName: 'accounts',
timestamps: false,
underscored: true,
},
);
export default Account;
import { Model, STRING, INTEGER } from 'sequelize';
import db from '.';
import Account from './account';
class User extends Model {
id!: number;
username!: string;
password!: string;
accountId!: any;
};
User.init({
id: {
type: INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
username: {
type: STRING(50),
allowNull: false,
},
password: {
type: STRING(200),
allowNull: false,
},
accountId: {
type: INTEGER,
// allowNull: false,
},
},
{
sequelize: db,
modelName: 'users',
tableName: 'users',
freezeTableName: true,
timestamps: false,
underscored: true,
hooks: {
afterCreate(user, _op) {
Account.create({ balance: 100})
}
},
}
);
Account.hasOne(User, {foreignKey: 'id', as: 'accountId'});
User.belongsTo(Account, {foreignKey: 'accountId', as: 'idAccount'});
export default User;
My migrations
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.createTable('users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
username: {
allowNull: false,
type: Sequelize.STRING(50),
},
password: {
allowNull: false,
type: Sequelize.STRING(200),
},
account_id: {
// allowNull: false,
type: Sequelize.INTEGER,
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
references: {
model: 'accounts',
key: 'id',
},
},
});
},
down: async (queryInterface, _Sequelize) => {
return queryInterface.dropTable('users');
},
};
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.createTable('accounts', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
balance: {
allowNull: false,
type: Sequelize.DECIMAL(13,2),
},
});
},
down: async (queryInterface, _Sequelize) => {
return queryInterface.dropTable('accounts');
},
};
register = async (req: Request, res: Response) => {
const { username, password } = req.body;
const registerUser = await this.userController.register({username, password});
res.status(200).json({registerUser});
}
I've tried going through the hooks and inserting auto increment as well

Sequelize: build a staggered triple association

I'm trying to make a save that corresponds to three models: Person ->(hasOne)-> ContactInfo ->(hasMany)-> Phone.
Models:
Person:
'use strict';
const chalk = require('chalk');
const { Model } = require('sequelize');
const { gender } = require("../utils/enumList");
const { ageCalculation } = require('../utils/extraFunctions');
module.exports = (sequelize, DataTypes) =>
{
class Person 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)
{
//Has one
Person.hasOne(models.ContactInfo, {
as: 'contactInfo_R',
foreignKey: {
name: "personId",
allowNull: false,
type: DataTypes.UUID,
unique: true,
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
Person.hasOne(models.Holder, {
as: 'holder_R',
foreignKey: {
name: "personId",
type: DataTypes.UUID,
allowNull: false,
unique: true,
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
Person.hasOne(models.Intermediary, {
as: 'intermediary_R',
foreignKey: {
name: "personId",
allowNull: false,
type: DataTypes.UUID,
unique: true,
},
onDelete: "CASCADE",
onUpdate: "CASCADE"
});
//Has many
Person.hasMany(models.Insured, {
as: "insured_R",
foreignKey: {
name: "personId",
allowNull: false,
type: DataTypes.UUID,
unique: false,
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
Person.init({
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV1,
primaryKey: true,
},
names: {
type: DataTypes.STRING,
allowNull: false,
},
surnames: {
type: DataTypes.STRING,
allowNull: false,
},
birth_date: {
type: DataTypes.DATEONLY,
allowNull: false,
},
age: {
type: DataTypes.VIRTUAL,
get()
{
return ageCalculation(this.getDataValue("birth_date"));
},
set(value)
{
throw new Error("No es necesario introducir la edad de la persona");
}
},
gender: {
type: DataTypes.ENUM(gender),
allowNull: false,
},
dni: {
type: DataTypes.STRING,
allowNull: true,
},
support_dni_address: {
type: DataTypes.STRING,
allowNull: true,
}
}, {
sequelize,
modelName: 'Person',
});
return Person;
};
ContactInfo:
'use strict';
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) =>
{
class ContactInfo 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
//Has many
ContactInfo.hasMany(models.Phone, {
as: "phone_R",
foreignKey: {
name: "contactInfoId",
type: DataTypes.UUID,
allowNull: false,
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
//Belong to
ContactInfo.belongsTo(models.Person, {
as: "person_R",
foreignKey: {
name: "personId",
type: DataTypes.UUID,
allowNull: false,
unique: true,
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
ContactInfo.init({
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV1,
primaryKey: true,
},
nation: {
type: DataTypes.STRING,
allowNull: false,
},
region: {
type: DataTypes.STRING,
allowNull: true,
},
city: {
type: DataTypes.STRING,
allowNull: true
},
address_1: {
type: DataTypes.STRING,
allowNull: true,
},
address_2: {
type: DataTypes.STRING,
allowNull: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: {
arg: true,
msg: "Por favor, usar un formato de correo electrónico valido"
},
},
},
}, {
sequelize,
modelName: 'ContactInfo',
});
return ContactInfo;
};
Phone:
'use strict';
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) =>
{
class Phone 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)
{
//Belong to
Phone.contactInfo = Phone.belongsTo(models.ContactInfo, {
as: "contactInfo_R",
foreignKey: {
name: "contactInfoId",
allowNull: false,
type: DataTypes.UUID,
unique: false
},
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
Phone.init({
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV1,
primaryKey: true,
},
nation_phone_code: {
type: DataTypes.STRING,
allowNull: false,
//TODO add predefined list
},
phone_number: {
type: DataTypes.STRING,
allowNull: false,
//TODO add formatting and validating
}
}, {
sequelize,
modelName: 'Phone',
});
return Phone;
};
Build Code:
let HolderPerson = await Models.Person.build({
names: personHolder_form.names,
surnames: personHolder_form.surnames,
birth_date: personHolder_form.birth_date,
gender: personHolder_form.gender,
dni: personHolder_form.dni,
support_dni_address: personHolder_form.support_dni_address,
contactInfo_R: {
nation: ContactInfoHolder_form.nation,
region: ContactInfoHolder_form.region,
city: ContactInfoHolder_form.city,
address_1: ContactInfoHolder_form.address_1,
address_2: ContactInfoHolder_form.address_2,
email: ContactInfoHolder_form.email,
phone_R: [
{ phone_number: '04269872654', nation_phone_code: '+58' },
{ phone_number: '02569871452', nation_phone_code: '+57' }
],
}
}, {
include: [{
association: {
model: Models.ContactInfo,
as: 'contactInfo_R'
},
include: [{
model: Models.Phone,
as: 'phone_R'
}]
}],
});
console.log(HolderPerson);
Console Error:
TypeError: Cannot read property 'name' of undefined
at Function._conformInclude (/home/sistemas/proyectos/Sistema_PreCris/node_modules/sequelize/lib/model.js:301:50)
at /home/sistemas/proyectos/Sistema_PreCris/node_modules/sequelize/lib/model.js:270:61
at Array.map (<anonymous>)
at Function._conformIncludes (/home/sistemas/proyectos/Sistema_PreCris/node_modules/sequelize/lib/model.js:270:39)
at new Model (/home/sistemas/proyectos/Sistema_PreCris/node_modules/sequelize/lib/model.js:104:24)
at new Person (/home/sistemas/proyectos/Sistema_PreCris/src/models/Person.js:10:5)
at Function.build (/home/sistemas/proyectos/Sistema_PreCris/node_modules/sequelize/lib/model.js:1326:12)
at primeraParte (/home/sistemas/proyectos/Sistema_PreCris/src/controllers/pruebas.js:86:52)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
I've done what I understand from the sequelize documentation but I can't get it to work. If I remove the association from the third model it works. I do not know what else to do.

What type should I assign to the parameter so that it does not give me this error?

import { Model, DataTypes } from 'sequelize';
interface IExtracciones {
id_extraccion: Number | null | undefined;
monto_extraido: Number;
fecha_de_extraccion: Date;
numero_de_cuenta: Number;
}
export default class Extracciones extends Model<IExtracciones> {}
Extracciones.init(
{
id_extraccion: {
type: DataTypes.INTEGER,
primaryKey: true,
},
monto_extraido: {
type: DataTypes.INTEGER,
allowNull: false,
},
fecha_de_extraccion: {
type: DataTypes.DATE,
allowNull: false,
},
numero_de_cuenta: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize: bd,
tableName: 'extracciones',
}
);
function agregaRelacion(m1: typeof Model /*error here*/, m2: any, fk: String) {
m1.hasOne(m2, { foreignKey: fk });
m2.hasOne(m1, { foreignKey: fk });
}
The 'this' context of type 'typeof Model' is not assignable to method's 'this' of type 'ModelStatic<Model<{}, {}>>'.
Type 'typeof Model' is not assignable to type 'new () => Model<{}, {}>'.
Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2684)
import { Model, DataTypes, Sequelize, ModelStatic } from 'sequelize';
interface IExtracciones {
id_extraccion: Number | null | undefined;
monto_extraido: Number;
fecha_de_extraccion: Date;
numero_de_cuenta: Number;
}
export default class Extracciones extends Model<IExtracciones> {}
Extracciones.init(
{
id_extraccion: {
type: DataTypes.INTEGER,
primaryKey: true,
},
monto_extraido: {
type: DataTypes.INTEGER,
allowNull: false,
},
fecha_de_extraccion: {
type: DataTypes.DATE,
allowNull: false,
},
numero_de_cuenta: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
// change new Sequeilze()
sequelize: new Sequelize(),
tableName: 'extracciones',
}
);
// m2 replace any with appropriate modelname if needed
/* corrected fk type (String compiles to javascript, shouldn't used as type) */
function agregaRelacion(m1: ModelStatic<Extracciones>, m2: ModelStatic<any>, fk: string) {
m1.hasOne(m2, { foreignKey: fk });
m2.hasOne(m1, { foreignKey: fk });
}
Solution
imagine we have a users table and our users have skills so it is a one to many
right?
UserModel
import { BuildOptions, DataTypes, Model, Sequelize } from "sequelize";
export interface UserAttributes {
id: number;
name: string;
email: string;
password: string;
middleName: string;
lastName: string;
secondLastName: string;
active: boolean;
createdAt?: Date;
updatedAt?: Date;
}
export interface UserModel extends Model<UserAttributes>, UserAttributes {}
export class User extends Model<UserModel, UserAttributes> {}
export type UserStatic = typeof Model & {
new (values?: object, options?: BuildOptions): UserModel;
};
export function UserFactory (sequelize: Sequelize) {
return <UserStatic>sequelize.define("users", {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
middleName: {
type: DataTypes.STRING,
allowNull: true,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
secondLastName: {
type: DataTypes.STRING,
allowNull: true,
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
});
}
SkillsModel
import { BuildOptions, DataTypes, Model, Sequelize } from "sequelize";
export interface SkillsAttributes {
skill: string;
}
export interface SkillsModel
extends Model<SkillsAttributes>,
SkillsAttributes {}
export type SkillsStatic = typeof Model & {
new (values?: object, options?: BuildOptions): SkillsModel;
};
export function SkillsFactory (sequelize: Sequelize) {
return <SkillsStatic>sequelize.define("skills", {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
skill: {
type: DataTypes.STRING,
unique: true,
},
});
}
now imagine we have a dir call anyName and in there we have
we are going to export users and skills from our index file
index
import { Sequelize } from "sequelize";
import { CourseFactory, CourseStatic } from "./courses";
import { EducationFactory, EducationStatic } from "./education";
import { ExperienceFactory, ExperienceStatic } from "./experience";
import { FieldsFactory, FieldsStatic } from "./fields-of-interets";
import { GeneralFactory, GeneralStatic } from "./general";
import { SkillsFactory, SkillsStatic } from "./skills";
import { SkillsTypeFactory, SkillsTypeStatic } from "./skills-type";
import { SocialMediaFactory, SocialMediaStatic } from "./social-media";
import { UserFactory, UserStatic } from "./users";
export interface DB {
sequelize: Sequelize;
User: UserStatic;
Skills: SkillsStatic;
SkillsType: SkillsTypeStatic;
Experience: ExperienceStatic;
Education: EducationStatic;
Course: CourseStatic;
General: GeneralStatic;
SocialMedia: SocialMediaStatic;
FieldsOfInterest: FieldsStatic;
}
const sequelize = new Sequelize(
(process.env.DB_NAME = "rest_resume_api"),
(process.env.DB_USER = "john"),
(process.env.DB_PASSWORD = "password"),
{
port: Number(process.env.DB_PORT) || 54320,
host: process.env.DB_HOST || "localhost",
dialect: "postgres",
pool: {
min: 0,
max: 5,
acquire: 30000,
idle: 10000,
},
}
);
const User = UserFactory(sequelize);
const Skills = SkillsFactory(sequelize);
const SkillsType = SkillsTypeFactory(sequelize);
const Experience = ExperienceFactory(sequelize);
const Education = EducationFactory(sequelize);
const Course = CourseFactory(sequelize);
const General = GeneralFactory(sequelize);
const SocialMedia = SocialMediaFactory(sequelize);
const FieldsOfInterest = FieldsFactory(sequelize);
SkillsType.belongsTo(Skills);
SkillsType.belongsToMany(User, { through: "users_has_skills" });
User.belongsToMany(SkillsType, { through: "users_has_skills" });
Experience.belongsToMany(User, { through: "user_has_experience" });
User.belongsToMany(Experience, { through: "user_has_experience" });
Education.belongsToMany(User, { through: "user_has_education" });
User.belongsToMany(Education, { through: "user_has_education" });
Course.belongsTo(User);
General.belongsTo(User);
SocialMedia.belongsToMany(User, { through: "user_has_social" });
User.belongsToMany(SocialMedia, { through: "user_has_social" });
FieldsOfInterest.belongsToMany(User, { through: "user_has_fields" });
User.belongsToMany(FieldsOfInterest, { through: "user_has_fields" });
export const db: DB = {
sequelize,
User,
Skills,
};

How to create a Many to Many association in sequelize and nodejs

I am trying to create a many to many relationship between user table and role table through userroles table.
After table creation the db looks just fine, I tried pretty much everything I found on the sequelize documentation and previous answers here, nothing seems to work.
I am getting this error: EagerLoadingError [SequelizeEagerLoadingError]: UserRoles is not associated to User!
Any idea of what am I doing wrong ? please help!
class User extends Model {
static associate(models) {
User.belongsToMany(models.Role, {
foreignKey: "user_id",
through:'UserRoles',
as:"users"
});
}
}
User.init(
{
user_id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
phone: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: "User",
}
);
class Role extends Model {
static associate(models) {
Role.belongsToMany(models.User, {
foreignKey: "role_id",
through:'UserRoles',
as:"roles"
});
}
}
Role.init(
{
role_id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique:true
},
role_name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
role_desc: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: "Role",
}
);
class UserRoles extends Model {
static associate(models) {
}
}
UserRoles.init(
{
userroles_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
// user_id: {
// type: DataTypes.UUID,
// defaultValue: DataTypes.UUIDV4,
// },
// role_id: {
// type: DataTypes.UUID,
// defaultValue: DataTypes.UUIDV4,
// },
},
{
sequelize,
modelName: "UserRoles",
}
);
const signup = (req, res) => {
console.log(req.body);
console.log("signup entry");
if (
!req.body.role ||
!req.body.email ||
!req.body.password ||
!req.body.name ||
!req.body.phone
) {
res.status(400).send({
msg: "Please pass role, email, password and name.",
});
} else {
sequelize.models.User.findOne({
where: {
email: req.body.email,
},
})
.then((duplicateemailfound) => {
if (duplicateemailfound) {
console.log(duplicateemailfound);
return res.status(400).json({
success: false,
message: "Email already registered",
});
} else {
let userRole = req.body.role.toLowerCase();
console.log("userRole:", userRole);
sequelize.models.Role.findOne({
where: {
role_name: userRole,
},
})
.then((foundRole) => {
// console.log(foundRole);
if (foundRole == null) {
return res.status(400).json({
success: false,
role: "null or not found",
});
}
// console.log("foundRole", foundRole); // .role_id
let addUser = {
email: req.body.email,
password: req.body.password,
name: req.body.name,
phone: req.body.phone,
role_id: foundRole.role_id,
};
sequelize.models.User.create(addUser, {
include: [{ model: sequelize.models.UserRoles }],
})
.then((newUser) => {
console.log("new user", newUser);
return res.status(201).json({
success: true,
newuser: newUser,
});
})
.catch((error) => {
console.log(error);
res.status(400).json({
success: false,
// message: "Duplicate Email was Found",
error: error.errors[0].message,
error: error,
});
});
})
.catch((error) => {
console.log(error);
res.status(400).json({
error: error,
msg: "bbb",
});
});
}
})
.catch((err) => {
console.log(err);
});
}
};
You create some a class for each Model and extend them with Model class of sequelize, this if fine.
Now, you define a static method inside the class named associate(model) where you define the rule for that class. This is fine because you used static which is required here to since it will be a property of the class, not of an object.
Then you call the initialize method (a in-built method of class Model). In the same way you need to call your defined associate.
Here is a problem, because in the structure that you have now, you can't call that method in it's own class file, becuase you need the other Model to pass it as parameter.
So there are 2 solutions:
Import your User model inside Role model file and call the static method, like this:
const User = require('User')
class Role extends Model {
static associate(model) {
Role.belongsToMany(model, {
foreignKey: "role_id",
through:'UserRoles',
as:"roles"
});
}
}
Role.init(
{
role_id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique:true
},
role_name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
role_desc: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: "Role",
}
);
Role.associate(User);
This will use your User model to pass it to the static method and finally to run the belongsToMany
Second solution would be to create an index file for your Models, where you import both of them and you can simply run that belongsToMany there, and then simply import that index file in the main file of your application, something like this:
User.js
const index = require('./../index.js');
const Sequelize = require('sequelize');
const Model = Sequelize.Model;
const sequelize = index.sequelize;
class User extends Model{}
User.init({
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
password: {
type: Sequelize.STRING,
allowNull: false
},
role: {
type: Sequelize.STRING,
allowNull: false
}
},{
sequelize,
modelName: 'user'
});
module.exports = {
User: User
}
Role.js will look the same but with your own model.
and index.js would look like this:
const Sequelize = require('sequelize');
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USERNAME, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: process.env.DB_DIALECT
});
exports.sequelize = sequelize;
const user = require('./models/User');
const role= require('./models/Role');
role.belongsToMany(user, {
foreignKey: "role_id",
through:'UserRoles',
as:"roles"
});
sequelize.sync(user);
sequelize.sync(role);
exports.db = {
user: user,
role: role
}

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

Resources