Related
This is my Diagram DATABASE : https://i.stack.imgur.com/CGAwh.png
I made models of my databases with SEQUELIZE like that :
MODEL : Level
module.exports = (sequelize, DataTypes) => {
const Level = sequelize.define(
'Level',
{
level_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
label: {
type: DataTypes.STRING,
allowNull: false,
unique: {
args: true,
msg: 'Level:Label already exist!',
},
validate: {
notEmpty: { msg: `Level:Label cannot be empty!` },
notNull: { msg: `Level:Label cannot be NULL!` },
},
},
ref: {
type: DataTypes.STRING,
allowNull: true,
},
description: {
type: DataTypes.TEXT,
allowNull: true,
},
},
{
tableName: 'levels',
timestamps: false,
}
);
Level.associate = (models) => {
Level.belongsToMany(models.Test, {
through: models.testHasLevel,
foreignKey: 'level_id',
otherKey: 'test_id',
timestamps: false,
});
};
return Level;
};
Model : TEST :
module.exports = (sequelize, DataTypes) => {
const Test = sequelize.define(
'Test',
{
test_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
label: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: { msg: `Test:label cannot be empty!` },
notNull: { msg: `Test:label cannot be NULL!` },
},
},
isInternal: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
validate: {
notEmpty: { msg: `Test:isInternal cannot be empty!` },
notNull: { msg: `Test:isInternal cannot be NULL!` },
},
},
parent_id: {
type: DataTypes.INTEGER,
defaultValue: null,
allowNull: true,
},
},
{
tableName: 'tests',
timestamps: false,
}
);
Test.associate = (models) => {
Test.belongsToMany(models.Level, {
through: models.testHasLevel,
foreignKey: 'test_id',
otherKey: 'level_id',
timestamps: false,
});
Test.hasMany(models.Test, { foreignKey: 'parent_id', as: 'children' });
};
return Test;
};
MODEL : TEST HAS MODEL
module.exports = (sequelize, DataTypes) => {
const testHasLevel = sequelize.define(
'testHasLevel',
{},
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
tableName: 'test_has_level',
timestamps: false,
}
);
testHasLevel.associate = (models) => {
testHasLevel.belongsTo(models.Test, {
foreignKey: 'test_id',
targetKey: 'test_id',
});
testHasLevel.belongsTo(models.Level, {
foreignKey: 'level_id',
targetKey: 'level_id',
});
};
return testHasLevel;
};
I made also SESSION MODEL :
module.exports = (sequelize, DataTypes) => {
const Session = sequelize.define(
'Session',
{
session_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
institut_id: {
type: DataTypes.INTEGER,
},
start: {
type: DataTypes.DATE,
},
end: {
type: DataTypes.DATE,
},
test_id: {
type: DataTypes.INTEGER,
},
level_id: {
type: DataTypes.INTEGER,
},
limitDateSubscribe: {
type: DataTypes.DATE,
},
placeAvailable: {
type: DataTypes.INTEGER,
},
},
{
tableName: 'sessions',
timestamps: false,
}
);
Session.associate = (models) => {
Session.hasMany(models.sessionHasUser, { foreignKey: 'session_id' });
};
return Session;
};
But i have no idea how to "BIND" SESSION with TEST_HAS_LEVEL with Sequelize ....
What should i change ? cause i know "composite key" are not allowed with the last version of sequelize.
In other term :
How associate properly a cross table with a one to many relationship to an other table ?
Model: Level
module.exports = (sequelize, DataTypes) => {
const Level = sequelize.define(
"Level",
{
level_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
label: {
type: DataTypes.STRING,
allowNull: false,
unique: {
args: true,
msg: "Level:Label already exist!",
},
validate: {
notEmpty: { msg: `Level:Label cannot be empty!` },
notNull: { msg: `Level:Label cannot be NULL!` },
},
},
ref: {
type: DataTypes.STRING,
allowNull: true,
},
description: {
type: DataTypes.TEXT,
allowNull: true,
},
},
{
tableName: "levels",
timestamps: false,
}
);
Level.associate = (models) => {
Level.hasMany(models.testHasLevel, {
foreignKey: "level_level_id",
as: "levels",
});
};
return Level;
};
Model: Test
module.exports = (sequelize, DataTypes) => {
const Test = sequelize.define(
"Test",
{
test_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
label: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: { msg: `Test:label cannot be empty!` },
notNull: { msg: `Test:label cannot be NULL!` },
},
},
isInternal: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
validate: {
notEmpty: { msg: `Test:isInternal cannot be empty!` },
notNull: { msg: `Test:isInternal cannot be NULL!` },
},
},
parent_id: {
type: DataTypes.INTEGER,
defaultValue: null,
allowNull: true,
},
},
{
tableName: "tests",
timestamps: false,
}
);
Test.associate = (models) => {
Test.hasMany(models.testHasLevel, {
foreignKey: "test_test_id",
as: "tests",
});
Test.hasMany(models.Test, { foreignKey: "parent_id", as: "children" });
};
return Test;
};
Model: Test has level
module.exports = (sequelize, DataTypes) => {
const testHasLevel = sequelize.define(
"testHasLevel",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
test_test_id: {
type: DataTypes.INTEGER,
},
level_level_id: {
type: DataTypes.INTEGER,
},
},
{
tableName: "test_has_level",
timestamps: false,
}
);
testHasLevel.associate = (models) => {
testHasLevel.belongsTo(models.Test, {
foreignKey: "test_test_id",
as: "tests",
});
testHasLevel.belongsTo(models.Level, {
foreignKey: "level_level_id",
as: "levels",
});
testHasLevel.hasMany(models.Session, {
foreignKey: "test_has_level_id",
as: "test_has_level",
});
};
return testHasLevel;
};
Model: Session
module.exports = (sequelize, DataTypes) => {
const Session = sequelize.define(
"Session",
{
session_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
institut_id: {
type: DataTypes.INTEGER,
},
start: {
type: DataTypes.DATE,
},
end: {
type: DataTypes.DATE,
},
test_has_level_id: {
type: DataTypes.INTEGER,
},
limitDateSubscribe: {
type: DataTypes.DATE,
},
placeAvailable: {
type: DataTypes.INTEGER,
},
},
{
tableName: "sessions",
timestamps: false,
}
);
Session.associate = (models) => {
Session.belongsTo(models.testHasLevel, {
foreignKey: "test_has_level_id",
as: "test_has_level",
});
};
return Session;
};
I have this error and can`t find a way arround it: EagerLoadingError [SequelizeEagerLoadingError]: grl_entidade is not associated to stn_matriz_gerada!
I have tryed many things, currently this is the way my app is:
stn_matriz_gerada.js
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('stn_matriz_gerada', {
conta: {
type: DataTypes.STRING,
allowNull: true,
primaryKey: true
},
v1: {
type: DataTypes.STRING,
allowNull: true
},
t1: {
type: DataTypes.STRING,
allowNull: true
},
v2: {
type: DataTypes.STRING,
allowNull: true
},
t2: {
type: DataTypes.STRING,
allowNull: true
},
v3: {
type: DataTypes.STRING,
allowNull: true
},
t3: {
type: DataTypes.STRING,
allowNull: true
},
v4: {
type: DataTypes.STRING,
allowNull: true
},
t4: {
type: DataTypes.STRING,
allowNull: true
},
v5: {
type: DataTypes.STRING,
allowNull: true
},
t5: {
type: DataTypes.STRING,
allowNull: true
},
v6: {
type: DataTypes.STRING,
allowNull: true
},
t6: {
type: DataTypes.STRING,
allowNull: true
},
v7: {
type: DataTypes.STRING,
allowNull: true
},
t7: {
type: DataTypes.STRING,
allowNull: true
},
valor: {
type: DataTypes.DOUBLE,
allowNull: true
},
tipo: {
type: DataTypes.STRING,
allowNull: true
},
tipo_int: {
type: DataTypes.INTEGER,
allowNull: true
},
natureza_valor: {
type: DataTypes.STRING,
allowNull: true
},
exercicio: {
type: DataTypes.INTEGER,
allowNull: true
},
mes: {
type: DataTypes.INTEGER,
allowNull: true
},
grl_entidade: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'grl_entidade',
key: 'id'
}
},
conteudo_txt: {
type: DataTypes.TEXT,
allowNull: true
}
}, {
sequelize,
tableName: 'stn_matriz_gerada',
schema: 'public',
timestamps: false
});
};
init-models.js
var DataTypes = require("sequelize").DataTypes;
var _grl_entidade = require("./grl_entidade");
var _grl_entidade_tipo = require("./grl_entidade_tipo");
var _grl_municipio = require("./grl_municipio");
var _grl_uf = require("./grl_uf");
var _stn_matriz_gerada = require("./stn_matriz_gerada");
function initModels(sequelize) {
var grl_entidade = _grl_entidade(sequelize, DataTypes);
var grl_entidade_tipo = _grl_entidade_tipo(sequelize, DataTypes);
var grl_municipio = _grl_municipio(sequelize, DataTypes);
var grl_uf = _grl_uf(sequelize, DataTypes);
var stn_matriz_gerada = _stn_matriz_gerada(sequelize, DataTypes);
grl_entidade_tipo.hasMany(grl_entidade,
{ foreignKey: { name: "grl_entidade_tipo"},
as: "grl_entidade_tipo_fk"},);
grl_entidade.belongsTo(grl_entidade_tipo,
{ foreignKey: { name: "grl_entidade_tipo"},
as: "grl_entidade_tipo_fk"},);
grl_municipio.hasMany(grl_entidade,
{ foreignKey: { name: "grl_municipio"},
as: "grl_municipio_fk"},);
grl_entidade.belongsTo(grl_municipio,
{ foreignKey: { name: "grl_municipio"},
as: "grl_municipio_fk"},);
grl_uf.hasMany(grl_municipio,
{ foreignKey: { name: "grl_uf"},
as: "grl_uf_fk"},);
grl_municipio.belongsTo(grl_uf,
{ foreignKey: { name: "grl_uf"},
as: "grl_uf_fk"},);
grl_entidade.hasMany(stn_matriz_gerada,
{ foreignKey: { name: "grl_entidade"},
as: "grl_entidade_fk"},);
stn_matriz_gerada.belongsTo(grl_entidade,
{ foreignKey: { name: "grl_entidade"},
as: "grl_entidade_fk"},);
return {
grl_entidade,
grl_entidade_tipo,
grl_municipio,
grl_uf,
stn_matriz_gerada,
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
MscService.js
class MscService {
static async getAllMscs() {
try {
return await database.stn_matriz_gerada.findAll();
} catch (error) {
throw error;
}
}
static async getAMsc(conta) {
try {
const theMsc = await database.stn_matriz_gerada.findAll({
where: { conta: Number(conta) },
include: [ {model: database.grl_entidade, as: 'grl_entidade_fk' }]
});
return theMsc;
} catch (error) {
console.log(error);
throw error;
}
}
}
export default MscService;
It has hasMany and belongsTo but stills give me the error of EagerLoadingError [SequelizeEagerLoadingError]: grl_entidade is not associated to stn_matriz_gerada!
Version: "sequelize": "^6.3.5",
Can anyone help me please?
I have checked this answer and made sure with both scenario are correct. But still having issue creating constraints:
Model:
user.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
username: {
type: DataTypes.STRING,
unique: true,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
}
}, {});
User.associate = function(models) {
models.User.hasMany(models.Answer);
};
return User;
};
answer.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Answer = sequelize.define('Answer', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
userId: {
type: DataTypes.INTEGER,
references: {
model: 'Users',
key: 'id'
},
allowNull: true
},
content: DataTypes.TEXT
}, {});
Answer.associate = function(models) {
models.belongsTo(models.User)
};
return Answer;
};
Migration
...-create-user.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING,
unique: true,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
...create-answer.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Answers', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
allowNull: true,
type: Sequelize.INTEGER
},
content: {
allowNull: false,
type: Sequelize.TEXT
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Answers');
}
};
What else might be the issue? Is it due to allowNull: true? But I am sure this should not be the case because I also tested using allowNull: false if it works, but it did not.
I have also tried model: User and .INTEGER(11) exactly but nothing work. I cannot see foreign key constraints on PHPMyAdmin.
You should add
userId: {
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id'
},
allowNull: true
}
in create-answer.js
instead of
userId: {
allowNull: true,
type: Sequelize.INTEGER
},
I have some issue with getting full data from db.
That are my models:
User
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'ID'
},
password: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'password'
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
field: 'email'
},
roleId: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'role',
key: 'ID'
},
field: 'role_id'
}
}, {
timestamps: false,
tableName: 'user'
});
};
Role
module.exports = function(sequelize, DataTypes) {
return sequelize.define('role', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'ID'
},
name: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
field: 'name'
},
description: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'description'
},
permission: {
type: DataTypes.INTEGER(11),
allowNull: false,
field: 'permission'
}
}, {
timestamps: false,
tableName: 'role',
});};
I want to get object of one specific user including all role content.
Somethink like
{
id: 4,
password: 'xxx',
email: 'adsads#saas.com',
role: {
id: 2,
name: 'admin'
description: 'ipsum ssaffa',
permission: 30
}
}
So I'm using:
User.findOne( { where: { id: req.userId }, include: [ Role ] } ).then( user =>{...});
but I get in the result err.message: "role is not associated to user"
And the simple question - what's wrong ? :)
*to handle models I'm using sequelize-cli
You get this error because you didn't add associate between the models
base on your json I see that each user only has one role, so you can either use belongsTo in role model or hasOne in user model
Should be something like this:
User.js
module.exports = function(sequelize, DataTypes) {
var user = sequelize.define('user', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'ID'
},
password: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'password'
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
field: 'email'
},
roleId: {
type: DataTypes.INTEGER(11),
allowNull: false,
references: {
model: 'role',
key: 'ID'
},
field: 'role_id'
}
}, {
timestamps: false,
tableName: 'user'
});
user.associate = function(models) {
user.hasOne(models.role, {foreignKey: 'id',sourceKey: 'roleId'});
}
return user;
};
Role.js
module.exports = function(sequelize, DataTypes) {
var role = sequelize.define('role', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'ID'
},
name: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
field: 'name'
},
description: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'description'
},
permission: {
type: DataTypes.INTEGER(11),
allowNull: false,
field: 'permission'
}
}, {
timestamps: false,
tableName: 'role',
});
role.associate = function(models) {
user.belongsTo(models.role, {foreignKey: 'id'});
}
return role;
};
You have to declare associations between your Models. If using Sequelize CLI make sure the static method associate is being called. Example:
/models.index.js
const Category = require('./Category');
const Product = require('./Product');
const ProductTag = require('./ProductTag');
const Tag = require('./Tag');
Category.associate({Product});
Product.associate({Category,Tag});
Tag.associate({Product});
module.exports={Category,Product,ProductTag,Tag};
and then the association in Category.js
'use strict';
const {Model,DataTypes} = require('sequelize');
const sequelize = require('../config/connection.js');
class Category extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method.
*/
static associate({Product}) {
// define association here
console.log('Category associated with: Product');
this.hasMany(Product, {
foreignKey: 'category_id',
onDelete: 'CASCADE'
});
}
}
Category.init({
category_id: {type: DataTypes.INTEGER, autoIncrement: true, allowNull: false, primaryKey: true},
category_name: {type: DataTypes.STRING, allowNull: false}
}, {
sequelize,
timestamps: false,
freezeTableName: true,
underscored: true,
modelName: "Category",
});
module.exports = Category;
I have the following model
(Migration) transaction.js
'use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('transactions', {
date: {
type: Sequelize.DATEONLY
},
transNo: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
accNo: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable('transactions');
}
};
(Model) transaction.js
'use strict';
const credit = require('./credit.js');
module.exports = function(sequelize, DataTypes) {
var transaction = sequelize.define('transaction', {
date: DataTypes.DATEONLY,
transNo: DataTypes.INTEGER,
accNo: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
transaction.hasOne(models.credit, {foreignKey: 'transNo'});
}
}
});
return transaction;
};
(Model) credit.js
module.exports = function(sequelize, DataTypes) {
var credit = sequelize.define('credit', {
transNo: DataTypes.INTEGER,
creNo: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
}
}
});
return credit;
};
(Migration) credit.js
` module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('credits', {
transNo: {
type: Sequelize.INTEGER
},
creNo: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable('credits');
}
};`
it still queries with the id column
Executing (default): SELECT transaction.id, transaction.date, transaction.accNo,.........(and so on).
how to disable the id column from being queried?
You simply need to set another column as your primary key and the id column won't be generated by default.
module.exports = function(sequelize, DataTypes) {
var credit = sequelize.define('credit', {
transNo: DataTypes.INTEGER,
{
creNo: DataTypes.INTEGER,
primaryKey: true //define a primaryKey
}
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
}
}
});
return credit;
};