Problem coding a weak entity in sequelize - mysql

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.

Related

I created oneToMany relation but how I can get the single record belongs to the many record in Sequalize

Tagcategories Model
export const TagCategories = sequelize.define(
"tag_categories",
{
categoryId: {
type: DataTypes.INTEGER,
field: "category_id",
autoIncrement: true,
primaryKey: true,
},
title: {
type: DataTypes.STRING(50),
field: "title",
allowNull: false,
unique: true,
},
},
);
TagCategories.hasMany(TagGroups, {
foreignKey: "categoryId",
sourceKey: "categoryId",
});
export default TagCategories;
TagGroups Model
export const TagGroups = sequelize.define(
"tag_groups",
{
tagGroupId: {
type: DataTypes.INTEGER,
field: "tag_group_id",
autoIncrement: true,
primaryKey: true,
},
categoryId: {
type: DataTypes.INTEGER,
field: "category_id",
allowNull: false,
},
title: {
type: DataTypes.STRING(50),
field: "title",
allowNull: false,
unique: true,
},
},
);
In the above models I establish oneToMany relationship between the TagCategories and TagGroups
But I want to fetch the record from the TagGroup table with the TagCategories details.
Thanks in advance
Did you look at examples in official documentation?
Also, you need to add an association from TagGroups to TagCategories:
// there is no need to indicate `sourceKey` if this field is a primary key
TagGroups.belongsTo(TagCategories, {
foreignKey: "categoryId",
});
It's better to define all associations in static functions and call all of them separately after all models will be registered.
See the question and my answer here how to do it
In your case, the final request would be something like this
const tagGroup = await TagGroups.findOne({
where: {
tagGroupId: groupId
},
include: [{
model: TagCategories
}]
})

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);
}
};

Sequelize Model exports a Function

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

How to populate table with foreign key values, using sequelize?

I have models: Business, Contributor, Feedback.
I have created relationship between Feedback and Contributor, and Feedback and Business like this:
Feedback.belongsTo(Business)
Feedback.belongsTo(Contributor)
The corresponding foreign key attributes are added to the table Feedback. Question is, how to populate them with IDs coming from Business and Contributor table records?
This approach only gets the first record. If I use findAll(), then I get undefined.
for (let assetsUrl of assetUrls) {
...
var businesses = null;
var reviews = null;
...
var timestamp = Math.floor(Date.now() / 1000);
var b_id = await Business.findOne({
attributes: ["id"],
})
var c_id = await Contributor.findOne({
})
businesses = await Business.upsert({
...
last_scraped: timestamp
});
reviews = await Review.upsert(
{
contributor_id: c_id.id,
business_id: b_id.id,
last_scraped: timestamp,
},
)
}
Business model:
class Business extends Model {}
Business.init(
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
site: {
type: Sequelize.STRING,
},
name: {
type: Sequelize.STRING,
},
business_type: {
type: Sequelize.STRING,
unique: false,
defaultValue: "",
},
address: {
type: Sequelize.TEXT,
// allowNull defaults to true
},
price: {
type: Sequelize.STRING,
},
url: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
last_scraped: {
type: Sequelize.INTEGER,
defaultValue: Math.floor(Date.now() / 1000)
},
},
{
sequelize,
modelName: "business",
timestamps: true,
createdAt: false,
updatedAt: false,
underscored: true
}
);
Business === sequelize.models.Business;
Business.sync();
Contributor model:
class Contributor extends Model {}
Contributor.init(
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
site: {
type: Sequelize.STRING,
},
name: {
type: Sequelize.STRING,
unique: false,
},
location: {
type: Sequelize.STRING,
unique: false,
},
photo: {
type: Sequelize.STRING,
unique: false,
},
url: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
status: {
type: Sequelize.SMALLINT,
},
last_scraped: {
type: Sequelize.INTEGER,
defaultValue: Math.floor(Date.now() / 1000)
},
},
{
sequelize,
modelName: "contributor",
timestamps: true,
createdAt: false,
updatedAt: false,
underscored: true,
}
);
Contributor === sequelize.models.Contributor;
Contributor.sync();
Feedback model:
class Feedback extends Model {}
Feedback.init(
{
contributor_id: {
type: Sequelize.INTEGER,
},
business_id: {
type: Sequelize.INTEGER,
},
date: {
type: Sequelize.STRING,
unique: false,
},
rating: {
type: Sequelize.STRING,
unique: false,
},
content: {
type: Sequelize.STRING,
unique: false,
},
last_scraped: {
type: Sequelize.INTEGER,
defaultValue: Math.floor(Date.now() / 1000)
},
},
{
sequelize,
modelName: "feedback",
timestamps: true,
createdAt: false,
updatedAt: false,
underscored: true,
}
);
Feedback.belongsTo(Contributor, { foreignKey: 'contributor_id' })
Feedback.belongsTo(Business, { foreignKey: 'business_id'})
Feedback=== sequelize.models.Review;
Feedback.sync();
A Good use case for model streaming but I think sequelize doesn't
support it yet
With your approch, using findOne combined with offset option you can
create/update the Feedback model like this.
// Get number of records to avoid unnecessary findOne in the loop
const bRecordCount = await Business.count();
const cRecordCount = await Contributor.count();
for (let i = 0; i < assetUrls.length; i++) {
const assetsUrl = assetUrls[i];
// ...
let bRecord = null;
let cRecord = null;
let options = {
attributes: ["id"],
// order by id to be sure we get different record each time
order: [['id', 'ASC']],
raw: true,
offset: i //skip already taken records
};
try {
if (i < bRecordCount && i < cRecordCount) {
bRecord = await Business.findOne(options)
cRecord = await Contributor.findOne(options)
}
if (bRecord && cRecord) {
feedback = await Feedback.upsert({
contributor_id: cRecord.id,
business_id: bRecord.id,
last_scraped: timestamp,
//...
});
}
} catch (err) {
console.log(err);
}
}
If you have many records you should consider using
findAll()
with offset and limit options,
then do a bulkCreate()
with updateOnDuplicate option to avoid making many database queries
To get Feedback items with certain attributes call findAll:
var feedback = await Feedback.findAll({
attributes: ['contributor_id', 'business_id', 'last_scraped']
})

How to add foreign key using sequelize mysql

"I have 2 tables "Users" and "Profile_personals". How do I add a foreign key constraint to my profile personals using my "user_id" primary that's inside my Users table? I'm working with node.js, sequelize mysql.
Users(parent Table):
const Sequelize = require('sequelize')
const db = require("../database/db.js")
module.exports = db.sequelize.define(
"users",
{
user_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
)
Personals(Child Table):
const Sequelize = require('sequelize')
const db = require("../database/db.js")
module.exports = db.sequelize.define(
'profile_personals',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
biography: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
)
Do it this way, I hope it's what you're looking for.
module.exports = db.sequelize.define(
'profile_personals',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
biography: {
type: Sequelize.STRING
},
// It is possible to create foreign keys:
user_id: {
type: Sequelize.INTEGER,
references: {
// This is a reference to another model
model: Users,
// This is the column name of the referenced model
key: 'user_id'
}
}
},
{
timestamps: false
}
);