Sequelize Model exports a Function - mysql

i have define this model:
const Sequelize = require('sequelize');
const db = require("../database/db")
var Reparacion = db.sequelize.define('reparaciones', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
descripcion: {
type: Sequelize.STRING(255),
allowNull: true
},
fecha_inicio: {
type: Sequelize.DATEONLY,
allowNull: true
},
fecha_fin: {
type: Sequelize.DATEONLY,
allowNull: true
},
},{});
module.exports=Reparacion
In other model when I define the foreing Key in other model, the methods HasMany and belongsTo doesn't works because I call them on a function:
const Reparacion = require("./reparacion")
console.log(typeof(Vehiculo))
console.log(typeof(Reparacion))
Vehiculo.hasMany(Reparacion,{foreingKey:"vehiculoId", onDelete: 'cascade', sourceKey:"matricula"})
Reparacion.belongsTo(Vehiculo)
The both console log return: "function"
What i have to change for define correctly the association??
EDIT
that is de "Vehiculo" model:
const Sequelize = require('sequelize');
const db = require("../database/db")
var Vehiculo = db.sequelize.define('vehiculos', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: true
},
matricula: {
type: Sequelize.STRING(45),
allowNull: false,
primaryKey: true,
},
marca: {
type: Sequelize.STRING(50),
allowNull: true
},
modelo: {
type: Sequelize.STRING(50),
allowNull: true
},
anio: {
type: Sequelize.INTEGER,
allowNull: true
},
color: {
type: Sequelize.STRING(20),
allowNull: true
},
puertas: {
type: Sequelize.INTEGER,
allowNull: true
},
motor: {
type: Sequelize.STRING(20),
allowNull: true
},
},{});
const Reparacion = require("./reparacion")
Vehiculo.hasMany(Reparacion,{foreingKey:"vehiculoMatricula", onDelete: 'cascade', sourceKey:"matricula"})
Reparacion.belongsTo(Vehiculo)
module.exports=Vehiculo

Well, it is expected that typeof Vehiculo and typeof Reparacion will return a function that happens because every constructor or class is a function in JS, so when you create a model for an entity it returns a function/constructor that can create an instance of an entity for you. So there is no problem with that.
And actually the documentation shows similar code https://sequelize.org/master/manual/assocs.html

Related

i am a fresher i need help on nodejs

i have three tables (questions , options , answers)
in these three table parent model is questions and then child is options and answers
so, i want to delete child data also calling by parent id
Here is questions models
import Sequelize from "sequelize";
import Exam from "../../models/exam.js";
import sequelize from "../../utilities/database.js";
const Question = sequelize.define("question", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
questiontext: {
type: Sequelize.STRING,
allowNull: true,
},
questiontexthindi: {
type: Sequelize.STRING,
allowNull: true,
},
questionImgURL: {
type: Sequelize.STRING,
allowNull: true,
},
description: {
type: Sequelize.TEXT,
allowNull: true,
},
examId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: Exam,
key: "id",
},
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Question;
options models
import Sequelize from "sequelize";
import sequelize from "../../utilities/database.js";
import Question from "./question.js";
const Option = sequelize.define("option", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
optiontext: {
type: Sequelize.STRING,
// (Sequelize.STRING),
allowNull: false,
isLength: [2, 6],
},
questionId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: Question,
key: "id",
onDelete: "CASCADE",
},
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Option;
Here is answers models
import Sequelize from "sequelize";
import sequelize from "../../utilities/database.js";
import Question from "./question.js";
import Option from "./option.js";
const Answer = sequelize.define("answer", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
questionId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: Question,
key: "id",
onDelete: "CASCADE",
},
},
optionId: {
type: Sequelize.INTEGER,
allowNull: true,
references: {
model: Option,
key: "id",
},
},
correctanswer: {
type: Sequelize.STRING,
allowNull: false,
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Answer;
Here is my controller
//models
import Question from "../../../models/model-tesportal/option.js";
//helpers
import { validationErrorHandler } from "../../../helpers/validation-error-handler.js";
export const deleteTestSeries = async (req, res, next) => {
validationErrorHandler(req, next);
const questionId = req.params.questionId;
try {
const result = await Question.destroy({
where: {
questionId: questionId,
},
});
if (result[0] === 0) {
const error = new Error("Question not found");
error.statusCode = 404;
return next(error);
}
res.status(201).json({
message: "Question Deleted successfully",
});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
i want to pass questionId in params and then delete data of that particular questionId will be deleted from parent and child tables
I got the solution from #geeks for geeks
i have to modify in my models where i wanna access those reference key Id
just look at my models now it works perfectly :
here is questions model {parent}
import Sequelize from "sequelize";
import Exam from "../../models/exam.js";
import sequelize from "../../utilities/database.js";
const Question = sequelize.define("question", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: "id", **<----- modify here**
},
questiontext: {
type: Sequelize.STRING,
allowNull: true,
},
questiontexthindi: {
type: Sequelize.STRING,
allowNull: true,
},
questionImgURL: {
type: Sequelize.STRING,
allowNull: true,
},
description: {
type: Sequelize.TEXT,
allowNull: true,
},
examId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: Exam,
key: "id",
},
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Question;
child - options model
import Sequelize from "sequelize";
import sequelize from "../../utilities/database.js";
import Question from "./question.js";
const Option = sequelize.define("option", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
optiontext: {
type: Sequelize.STRING,
// (Sequelize.STRING),
allowNull: false,
isLength: [2, 6],
},
questionId: {
type: Sequelize.INTEGER,
allowNull: false,
onDelete: "CASCADE", **<----- modify here**
references: {
model: Question,
key: "id",
FOREIGNKEY: "id", **<----- modify here**
},
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Option;
child - answers models
import Sequelize from "sequelize";
import sequelize from "../../utilities/database.js";
import Question from "./question.js";
import Option from "./option.js";
const Answer = sequelize.define("answer", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
questionId: {
type: Sequelize.INTEGER,
allowNull: false,
onDelete: "CASCADE", **<----- modify here**
references: {
model: Question,
key: "id",
FOREIGNKEY: "id", **<----- modify here**
},
},
optionId: {
type: Sequelize.INTEGER,
allowNull: true,
references: {
model: Option,
key: "id",
},
},
correctanswer: {
type: Sequelize.STRING,
allowNull: false,
},
isActive: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
});
export default Answer;
main code controller
//models
import Question from "../../../models/model-tesportal/question.js";
//helpers
import { validationErrorHandler } from "../../../helpers/validation-error-handler.js";
export const deleteTestSeries = async (req, res, next) => {
validationErrorHandler(req, next);
try {
const result = await Question.destroy({
where: {
id: req.params.questionId,
},
});
if (result[0] === 0) {
const error = new Error("Question not found");
error.statusCode = 404;
return next(error);
}
res.status(201).json({
message: "Hey Admin Question Deleted successfully",
});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};

Trying to join parent / primary table to child / foreign table in sequelize

I'm trying to get all my articles data from articles table but also user data from users table i've made. I using sequelize to build database to MySQL database and also as a ORM, here's the snippet code
USER TABLE
const User = sequelize.define('users', ({
id: {
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
nama: {
type: DataTypes.STRING(50),
allowNull: false,
},
email: {
type: DataTypes.STRING(50),
allowNull: false,
},
password: {
type: DataTypes.STRING(50),
allowNull: false,
}
}))
ARTICLES CODE
const Articles = sequelize.define('articles', ({
id: {
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: false
},
gambar: {
type: DataTypes.STRING,
allowNull: false
},
userId: {
type: DataTypes.BIGINT,
allowNull: false,
}
}))
the relation
User.hasMany(Articles, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
Articles.belongsTo(User, {
foreignKey: 'userId'
})
the ORM i've try
Articles.findAll({
include: [User]
})
it is always return that users table is not associated to artiles
You have to use as key word during creating relation ship.
Articles.belongsTo(User, {
as: 'user',
foreignKey: 'userId'
})
and then update form
Articles.findAll({include: [{
model: model.User,
as: 'user'
}]})

Sequelize hasMany is working fine but the inverse relation is not working

I am trying to work with mysql relations in Node Js(express Js) using Sequelize.
User.hasMany(Post); work just fine, but when i try to inverse it in Post model like: Post.belongsTo(User);
got this error:
throw new Error(${source.name}.${_.lowerFirst(Type.name)} called with something that's not a subclass of Sequelize.Model);
Error: post.belongsTo called with something that's not a subclass of Sequelize.Model
User model like:
const Sequelize = require('sequelize');
const db = require('../config/db');
const Post = require('./Post');
const User = db.define('user', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
notNull: true,
primaryKey: true
},
name: {
type: Sequelize.STRING,
notNull: true
},
email: {
type: Sequelize.STRING,
notNull: true
},
password: {
type: Sequelize.STRING,
notNull: true
}
});
User.hasMany(Post);
module.exports = User;
And Post model like:
const Sequelize = require('sequelize');
const db = require('../config/db');
const User = require('./User');
const Post = db.define('post', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
notNull: true,
primaryKey: true
},
title: {
type: Sequelize.STRING,
notNull: true
},
description: {
type: Sequelize.TEXT,
notNull: true
},
author: {
type: Sequelize.STRING,
notNull: true
}
});
Post.belongsTo(User);
module.exports = Post;
How can i solve this problem?
Thanks everyone...
You should correct your model definition exports as functions and define associate function in each model definition function like this and call it all after all models are registered in some module like database.js:
user.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
notNull: true,
primaryKey: true
},
...
User.associate = function (models) {
User.hasMany(models.Post)
}
post.js
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define('post', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
notNull: true,
primaryKey: true
},
...
Post.associate = function (models) {
Post.belongsTo(models.User)
}

Problem coding a weak entity in sequelize

I am creating a cinema application. I have modeled the database on mySql but I am having trouble migrating it to Sequelize. I have followed the documentation but I am getting a lot of different errors.
I have tried using associations and indexes (as it should be). This is the model I am trying to make.
OCCUPIED_SEATS is composed of only two foreign keys and both make a unique index.
OCCUPIED_SEATS:
const SEATS = require("./Seats");
const SCREENING = require("./Screening");
const OCCUPIED_SEATS = sequelize.define("OCCUPIED_SEATS", {
//SEATS_ID
//SCREENING_ID
},
{
indexes: [
{
unique: true,
fields: [SEAT_ID, SCREENING_ID]
}
],
underscored: true
}
);
module.exports = OCCUPIED_SEATS;
SEATS:
const OCCUPIED_SEATS = require("./Occupied_Seats");
const SEATS = sequelize.define("SEATS", {
SEATS_ID: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true
},
ROW: {
type: Sequelize.STRING,
allowNull: false,
},
COLUMN: {
type: Sequelize.INTEGER,
allowNull: false
},
},
{
underscored: true
}
);
SEATS.hasMany(OCCUPIED_SEATS, {foreignKey: 'SEAT_ID'})
module.exports = SEATS;
SCREENING:
const OCCUPIED_SEATS = require("./Occupied_Seats");
const SCREENING = sequelize.define("SCREENING", {
SCREENING_ID: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true
},
SCREENING_START_TIME: {
type: Sequelize.TIME,
allowNull: false,
},
DATE: {
type: Sequelize.DATE,
allowNull: false
}
},
{
underscored: true,
indexes: [
{
unique: true,
fields: [ROOM_ID, SCREENING_START_TIME, DATE]
}
]
}
);
SCREENING.hasMany(OCCUPIED_SEATS, {foreignKey: 'SCREENING_ID'});
module.exports = SCREENING;
The error I am getting when I try this is:
[💻] Error: SEATS.hasMany called with something that's not a subclass of Sequelize.Model
How should I code the model?
Looks like in the new version of Sequelize you have to define your models through Sequelize.Model type:
class Seats extends Sequelize.Model {}
Seats.init({
id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true
},
row: {
type: Sequelize.STRING,
allowNull: false,
},
...
});
module.exports = Seats;
And then somewhere else:
Seats.hasMany(OccupiedSeatc, {foreignKey: 'SEAT_ID'})
See model definition docs and accociation docs.

How to define unique index on multiple columns in sequelize

How do I define a unique index on a combination of columns in sequelize. For example I want to add a unique index on user_id, count and name.
var Tag = sequelize.define('Tag', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
},
count: {
type: DataTypes.INTEGER(11),
allowNull: true
},
name: {
type: DataTypes.STRING,
allowNull: true,
})
You can refer to this doc http://docs.sequelizejs.com/en/latest/docs/models-definition/#indexes
You will need to change your definition like shown below and call sync
var Tag = sequelize.define('Tag', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
},
count: {
type: DataTypes.INTEGER(11),
allowNull: true
},
name: {
type: DataTypes.STRING,
allowNull: true,
}
},
{
indexes: [
{
unique: true,
fields: ['user_id', 'count', 'name']
}
]
});
I have same issue to applied composite unique constraint to multiple
columns but nothing work with Mysql, Sequelize(4.10.2) and NodeJs
8.9.4 finally I fixed through following code.
queryInterface.createTable('actions', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
system_id: {
type: Sequelize.STRING,
unique: 'actions_unique',
},
rule_id: {
type: Sequelize.STRING,
unique: 'actions_unique',
},
plan_id: {
type: Sequelize.INTEGER,
unique: 'actions_unique',
}
}, {
uniqueKeys: {
actions_unique: {
fields: ['system_id', 'rule_id', 'plan_id']
}
}
});
If the accepted one is not working then try the below code. It worked for me in my case rather the accepted one.
var Tag = sequelize.define('Tag', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
unique: 'uniqueTag',
},
count: {
type: DataTypes.INTEGER(11),
allowNull: true,
unique: 'uniqueTag',
},
name: {
type: DataTypes.STRING,
allowNull: true,
unique: 'uniqueTag',
}
});
I tried to create an index on a single column.
This worked for me. Hope this helps.
Model
module.exports = (sequelize, DataTypes) => {
const Tag = sequelize.define(
"Tag",
{
name: { type: DataTypes.STRING, unique: true },
nVideos: DataTypes.INTEGER
},
{
indexes: [
{
unique: true,
fields: ["name"]
}
]
}
);
return Tag;
};
Migration
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable(
"Tags",
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING,
unique: "unique_tag"
},
nVideos: { type: Sequelize.INTEGER },
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
},
{
uniqueKeys: {
unique_tag: {
customIndex: true,
fields: ["name"]
}
}
}
);
},
down: queryInterface => {
return queryInterface.dropTable("Tags");
}
};
I prefer sequelize sync method with composite unique, If not passing indexes name u will get a error as below on adding many indexes in index array.
error: SequelizeDatabaseError: Identifier name 'LONG_NAME' is too long
module.exports = function (sequelize: any, DataTypes: any) {
return sequelize.define('muln_user_goals_transaction', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING(),
allowNull: false,
},
email: {
type: DataTypes.STRING(),
allowNull: false,
},
phone: {
type: DataTypes.STRING(),
allowNull: false,
},
amount: {
type: DataTypes.INTEGER(8),
allowNull: false
},
deleted: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
}, {
tableName: 'muln_user_goals_transaction',
timestamps: false,
indexes: [
{
name: 'unique_index',
unique: true,
fields: ['name', 'email', 'phone', 'amount', 'deleted']
}
],
defaultScope: {
where: {
deleted: false
}
}
});
};
Sequelize composite unique (manual)
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Model', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
fieldOne: {
type: Sequelize.INTEGER,
unique: 'uniqueTag',
allowNull: false,
references: {
model: 'Model1',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
},
fieldsTwo: {
type: Sequelize.INTEGER,
unique: 'uniqueTag',
allowNull: false,
references: {
model: 'Model2',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
.then(function() {
return queryInterface.sequelize.query(
'ALTER TABLE `UserFriends` ADD UNIQUE `unique_index`(`fieldOne`, `fieldTwo`)'
);
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Model');
}
};