sirs. I have 2 models in sequelize ,Project and User. Relationship between this two models is many-to-many. Fot this relation, I have created projectuser. But when i trying to insert intoprojectuser console gives me ReferenceError: Cannot access 'projectuser' before initialization error. [NodeJs][Sequelize] ReferenceError: Cannot access 'ModelName' before initialization I have tried this solution but i think it is too complex solution. Can you please help me?
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Project extends Model {
static associate(models) {
const { User, Issue, projectuser } = models;
this.belongsToMany(User, {
as: "project_users",
foreignKey: "project_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.hasMany(Issue, {
as: "project_issues",
foreignKey: "project_id",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
Project.init(
{
project_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
projectname: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
},
projecturl: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "Project",
}
);
return Project;
};
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
const { Commet, Project, Issue, projectuser, issueuser } = models;
this.hasMany(Commet, {
foreignKey: "user_id",
as: "user_commets",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Project, {
as: "project_user",
foreignKey: "user_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Issue, {
as: "user_issues",
foreignKey: "user_id",
through: issueuser,
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
User.init(
{
user_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
role: {
type: DataTypes.STRING,
allowNull: false,
validate: {
roleValidator(role) {
let rolet = role.toLowerCase();
if (roles[rolet] === undefined) {
throw new Error("Invalid Role");
}
},
},
},
username: { type: DataTypes.STRING, allowNull: false },
usersurname: { type: DataTypes.STRING, allowNull: false },
avatarURL: { type: DataTypes.STRING, allowNull: true },
password: {
type: DataTypes.STRING,
validate: {
passwordValidator(password) {
if (password.length <= 5) {
throw new Error("Cannot be less than 5 characters");
}
},
},
},
email: {
type: DataTypes.STRING,
unique: true,
validate: { isEmail: true },
},
},
{
sequelize,
modelName: "User",
}
);
return User;
};
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class projectuser 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
}
}
projectuser.init({
deneme: DataTypes.STRING
}, {
sequelize,
modelName: 'projectuser',
});
return projectuser;
};
Related
Good evenings,fine sirs. I am working with Sequelize with NodeJS. I created Many-to-many association between two table User and Project.
//This is Project Model
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Project extends Model {
static associate(models) {
const { User, Issue } = models;
this.belongsToMany(User, {
as: "project_users",
foreignKey: "project_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.hasMany(Issue, {
as: "project_issues",
foreignKey: "project_id",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
Project.init(
{
project_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
projectname: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING,
},
projecturl: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "Project",
}
);
return Project;
};
//This is User Model
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
const { Commet, Project, Issue } = models;
this.hasMany(Commet, {
foreignKey: "user_id",
as: "user_commets",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Project, {
as: "project_user",
foreignKey: "user_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Issue, {
as: "user_issues",
foreignKey: "user_id",
through: "issueuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
User.init(
{
user_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
role: {
type: DataTypes.STRING,
allowNull: false,
validate: {
roleValidator(role) {
let rolet = role.toLowerCase();
if (roles[rolet] === undefined) {
throw new Error("Invalid Role");
}
},
},
},
username: { type: DataTypes.STRING, allowNull: false },
usersurname: { type: DataTypes.STRING, allowNull: false },
avatarURL: { type: DataTypes.STRING, allowNull: true },
password: {
type: DataTypes.STRING,
validate: {
passwordValidator(password) {
if (password.length <= 5) {
throw new Error("Cannot be less than 5 characters");
}
},
},
},
email: {
type: DataTypes.STRING,
unique: true,
validate: { isEmail: true },
},
},
{
sequelize,
modelName: "User",
}
);
return User;
};
My question may be silly but, do i need to create junction table manually to access it from my code or is there any way to access it without creating it? Thank you for your answers.
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.
When I try to insert new category, I got this error:
error: column "image" does not exist
sql: 'INSERT INTO "Categories" ("id","createdAt","updatedAt") VALUES (DEFAULT,$1,$2) RETURNING "id","image","title","createdAt","updatedAt";'
The problem is that it doesn't insert name and other values and returns columns belong to post table.
My guesses are the problem of sequelize-cli and sequelize version or missing something in models or migrations.
I only insert values into name, createdAt and updatedAt column:
await Category.create({
name: req.body.name,
createdAt: new Date(),
updatedAt: new Date()
});
My category model:
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Category extends Model {
static associate(models) {
Category.hasMany(models.Post, { as: "posts", foreignKey: "categoryId" });
}
}
Category.init(
{
name: DataTypes.STRING
},
{
sequelize,
modelName: "Category"
}
);
return Category;
};
My Post Model:
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Post extends Model {
static associate(models) {
Post.belongsTo(models.Category, { foreignKey: "categoryId", onDelete: "CASCADE", as: "category" });
}
}
Post.init(
{
title: DataTypes.STRING,
image: DataTypes.STRING,
content: DataTypes.TEXT,
categoryId: DataTypes.INTEGER
},
{
sequelize,
modelName: "Post"
}
);
return Post;
};
Post migration:
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("Posts", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
image: {
type: Sequelize.STRING
},
content: {
type: Sequelize.TEXT
},
categoryId: {
type: Sequelize.INTEGER,
allowNull: false,
onDelete: "CASCADE",
references: {
model: "Categories",
key: "id"
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
Category migration:
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("Categories", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
I couldn't find solution for this, therefor I used sequelize.query
I have a many to many relationship between the tables DeliveryOrder and GasBottle with the extra field Amount, but when i try to insert some values in this table, sequelize change´s the field order.
My models:
const {Model,DataTypes} = require ('sequelize')
class GasBottle extends Model{
static init(sequelize){
super.init({
type: DataTypes.INTEGER,
costPrice: DataTypes.DOUBLE,
sellPrice: DataTypes.DOUBLE
},{sequelize})
}
static associate({ DeliveryOrder,DeliveryOrderGasBottle}) {
GasBottle.belongsToMany(DeliveryOrder, {
through: DeliveryOrderGasBottle,
as: "deliveryOrders",
foreignKey: "deliveryOrderId",
});
}
}
module.exports = GasBottle
const { Model, DataTypes } = require("sequelize");
class DeliveryOrder extends Model {
static init(sequelize) {
super.init(
{
status: DataTypes.INTEGER,
latitude: DataTypes.INTEGER,
longitude: DataTypes.INTEGER,
delivererId: {
type: DataTypes.INTEGER,
references: {
model: "Deliverer",
key: "id",
},
},
},
{ sequelize }
);
}
static associate({ Deliverer, GasBottle, DeliveryOrderGasBottle }) {
DeliveryOrder.belongsTo(Deliverer, { foreignKey: "delivererId" });
DeliveryOrder.belongsToMany(GasBottle, {
through: DeliveryOrderGasBottle,
as: "bottles",
foreignKey: "gasBottleId",
});
}
}
module.exports = DeliveryOrder;
const { Model, DataTypes } = require("sequelize");
class DeliveryOrderGasBottle extends Model {
static init(sequelize) {
super.init(
{
gasBottleId: {
type: DataTypes.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
},
deliveryOrderId: {
type: DataTypes.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
},
amount: DataTypes.INTEGER,
},
{ sequelize }
);
}
}
module.exports = DeliveryOrderGasBottle;
My migration file:
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable("DeliveryOrderGasBottle", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
gasBottleId: {
type: Sequelize.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
deliveryOrderId: {
type: Sequelize.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
amount:{
type: Sequelize.DOUBLE,
allowNull: false,
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable("DeliveryOrderGasBottle");
},
};
My association:
const deliveryOrder = await DeliveryOrder.create(obj);
bottlesToAdd.map(async (bottle) => {
const db_bottle = await GasBottle.findByPk(bottle.id);
await deliveryOrder.addBottle(db_bottle, {
through: { amount: parseInt(bottle.amount) },
});
On insert, sequelize is changing the order of the ids, resulting in a constraint error because i dont have the id´s on the respective tables
INSERT INTO "DeliveryOrderGasBottle" ("gasBottleId","deliveryOrderId","amount","createdAt","updatedAt") VALUES (18,1,42,'2020-06-27 19:17:26.204 +00:00','2020-06-27 19:17:26.204 +00:00')
I am trying to delete all contents from a n:m association table.
I have the tables: MenuItems and UserGroups like this, but I am using migrations to genererate the database:
MenuItems
module.exports = (sequelize, DataTypes) => {
const MenuItems = sequelize.define('MenuItems', {
title: {
type: DataTypes.STRING,
allowNull: false
}
// more fields...
}, {
freezeTableName: true
});
MenuItems.associate = function(models) {
MenuItems.belongsToMany(models.UserGroups, { through: 'MenuItemUserGroups' });
};
UserGroups
module.exports = (sequelize, DataTypes) => {
const UserGroups = sequelize.define('UserGroups', {
name: {
type: DataTypes.STRING,
unique: true
}
}, {
freezeTableName: true
});
UserGroups.associate = function(models) {
// Associations to other models
UserGroups.belongsToMany(models.MenuItems, { through: 'MenuItemUserGroups' });
};
return UserGroups;
};
The association table is generated with the following migration:
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('MenuItemUserGroups', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
menuItemId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'MenuItems',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
},
userGroupId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'UserGroups',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
}
//more fields
});
}
I try to delete using the following sequelize code:
models.MenuItems.findOne({ where: { id: 1 }, include: [{ all: true }] }).then(menuItem => {
if(req.body.userGroups.length <= 0) {
menuItem.setUserGroups([]).then(result => {
console.log(result);
});
The SQL that is generated is the following:
DELETE FROM `MenuItemUserGroups` WHERE `UserGroupId` = 1 AND `MenuItemId` IN (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
[ 0 ]
where UserGroupId IN (NULL) will always return nothing. If that part is removed, the query works.
Could this have something to do with some naming convention?