Sequelize - 2 optional foreign key in a table - mysql

There are 3 tables attendance_record, student, teacher with below relationship.
student(1) : attendance_record(Many) > studentId(foreign key)
teacher(1) : attendance_record(Many) > teacherId(foreign key)
When I create a attendance_record, the payload will be like this:
{
"studentId": "xxxxx",
"isAttended": true,
"date": 1625020428
}
It shows below error
Cannot add or update a child row: a foreign key constraint fails (`my_db`.`attendance_record`, CONSTRAINT `attendance_record_ibfk_34` FOREIGN KEY (`teacherId`) REFERENCES `teacher` (`id`) ON DELETE CASCADE O)
I know it's because of I do not include teacherId in the payload, but I want it to be optional(only studentId OR teacherId in payload).
How am I suppose to do it
attendance-record.model.js
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const attendanceRecord = sequelizeClient.define('attendance_record', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
studentId: {
allowNull: false,
type: DataTypes.UUID,
references: { model: 'student', key: 'id' },
defaultValue: Sequelize.UUIDV4,
unique: 'studentId_foreign_idx'
},
teacherId: {
allowNull: false,
type: DataTypes.UUID,
references: { model: 'teacher', key: 'id' },
defaultValue: Sequelize.UUIDV4,
unique: 'teacherId_foreign_idx'
},
isAttended: {
type: DataTypes.BOOLEAN,
},
date:{
type: DataTypes.DATE,
},
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
attendanceRecord.associate = function (models) {
attendanceRecord.belongsTo(models.student,{
as: 'students',
foreignKey: 'studentId'
});
attendanceRecord.belongsTo(models.teacher, {
as: 'teachers',
foreignKey: 'teacherId'
});
};
return attendanceRecord;
};
student.model.js
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const student = sequelizeClient.define('student', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
email: {
type: DataTypes.STRING,
allowNull: false,
isEmail: true,
unique: 'email'
},
firstName:{
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
},
lastName:{
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
}
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
student.associate = function (models) {
student.hasMany(models.attendance_record,{
foreignKey: 'studentId'
});
};
return student;
};
teacher.model.js
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const teacher = sequelizeClient.define('teacher', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
email: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
teacher.associate = function (models) {
teacher.hasMany(models.attendance_record,{
foreignKey: 'teacherId'
})
};
return teacher;
};

Related

Creating Associations with sequelize and mysql

I am trying to create seqeulize models in nodejs app on mysql db. However, When I run the codes, foreign keys are not being created as intended.
This are my models:
Category Model
"use strict";
module.exports = (sequelize, DataTypes) => {
const Category = sequelize.define("Category", {
category_id: {
type: DataTypes.STRING(255),
unique: true,
primaryKey: true,
},
name: { type: DataTypes.STRING, unique: true, allowNull: false },
slug: { type: DataTypes.STRING, unique: true, allowNull: false },
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal(
"CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
),
},
});
Category.associate = (models) => {
Category.hasMany(models.Product);
};
return Category;
};
Product Model
"use strict";
module.exports = (sequelize, DataTypes) => {
const Product = sequelize.define("Product", {
product_id: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
slug: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
sku: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
short_description: {
type: DataTypes.TEXT,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: false,
},
price: {
type: DataTypes.DECIMAL,
allowNull: false,
min: 1,
},
discount: {
type: DataTypes.DECIMAL,
allowNull: true,
},
quantity: {
type: DataTypes.INTEGER,
},
vat: {
type: DataTypes.DECIMAL,
allowNull: true,
},
tags: {
type: DataTypes.STRING(255),
allowNull: true,
},
rate: {
type: DataTypes.INTEGER,
allowNull: true,
},
points: {
type: DataTypes.INTEGER,
allowNull: true,
},
new: {
type: DataTypes.VIRTUAL,
get() {
var msPerDay = 8.64e7;
// Copy dates so don't mess them up
var x0 = new Date(this.getDataValue("created_at"));
var x1 = new Date();
// Set to noon - avoid DST errors
x0.setHours(12, 0, 0);
x1.setHours(12, 0, 0);
// Round to remove daylight saving errors
return Math.round((x1 - x0) / msPerDay) <= 30;
},
set(value) {
throw new Error("Can't set Product.new property.");
},
},
thumb_image: {
type: DataTypes.STRING,
allowNull: true,
get() {
if (this.getDataValue("thumb_image")) {
return JSON.parse(this.getDataValue("thumb_image"));
}
return [];
},
set(val) {
this.setDataValue("thumbImage", JSON.stringify(val));
},
},
images: {
type: DataTypes.STRING,
allowNull: true,
get() {
if (this.getDataValue("images")) {
return JSON.parse(this.getDataValue("images"));
}
return [];
},
set(val) {
this.setDataValue("images", JSON.stringify(val));
},
},
featured: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal(
"CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
),
},
});
Product.associate = (models) => {
Product.belongsTo(models.Category, {
foreignKey: "category_id",
});
Product.belongsTo(models.Brand, {
foreignKey: "brand_id",
});
Product.belongsTo(models.CartItem, {
foreignKey: "cart_id",
});
};
return Product;
};
Brand Model
"use strict";
module.exports = (sequelize, DataTypes) => {
const Brand = sequelize.define("Brand", {
brand_id: {
type: DataTypes.STRING(255),
unique: true,
primaryKey: true,
},
name: { type: DataTypes.STRING, unique: true, allowNull: false },
slug: { type: DataTypes.STRING, unique: true, allowNull: false },
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal(
"CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
),
},
});
Brand.associate = (models) => {
Brand.hasMany(models.Product);
};
return Brand;
};
And these is my Models/index.js file
/* eslint-disable no-undef */
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../../config/config.js")[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
}
db.sequelize = sequelize;
db.Sequelize = Sequelize;
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize
.sync({ force: process.env.NODE_ENV === "development" })
.then(() => {
console.log("Drop and re-sync db.");
});
module.exports = db;
Now when I run the server, I expected the products table to have the fields category_id and brand_id. However, am getting additional fields brand_brand_id and category_category_id on the products table.
Besides, I cannot retrieve the categories, brands and products with the include properties when fecthing data.
What I want is to have the products table properly created in the database with the required foreign keys
Since you have customized foreign keys you have to indicate them in both paired associations:
Category.associate = (models) => {
Category.hasMany(models.Product, { foreignKey: "category_id" });
};
Product.associate = (models) => {
Product.belongsTo(models.Category, {
foreignKey: "category_id",
});
Product.belongsTo(models.Brand, {
foreignKey: "brand_id",
});
Product.belongsTo(models.CartItem, {
foreignKey: "cart_id",
});
};
Brand.associate = (models) => {
Brand.hasMany(models.Product, { foreignKey: "brand_id" });
};

How to use add Methods with belongsToMany in Sequelize?

I am attempting to add a product to my cartitems Table
using sequilize:
Product.belongsTo(User, { constraints: true, onDelete: 'CASCADE' });
User.hasMany(Product);
User.hasOne(Cart);
Cart.belongsTo(User);
Cart.belongsToMany(Product, { through: CartItem });
Product.belongsToMany(Cart, { through: CartItem });
Here is my Product Model:
const Product = sequelize.define('product', {
id: {
type: Sequelize.STRING,
allowNull: false,
primaryKey: true,
},
title: {
type: Sequelize.STRING,
allowNull: false,
},
price: {
type: Sequelize.INTEGER,
allowNull: false,
},
imageURL: {
type: Sequelize.STRING,
allowNull: false,
},
description: {
type: Sequelize.STRING,
allowNull: false,
},
});
module.exports = Product;
Here is my Cart Model:
const Cart = sequelize.define('cart', {
id: {
type: Sequelize.STRING,
allowNull: false,
primaryKey: true,
},
});
module.exports = Cart;
Here is my User Model:
const User = sequelize.define('user', {
id: {
type: Sequelize.STRING,
allowNull: false,
primaryKey: true,
},
fullName: {
type: Sequelize.STRING,
allowNull: false,
},
email: {
type: Sequelize.STRING,
allowNull: false,
},
});
module.exports = User;
Here is my Cart-Item Model:
const CarteItem = sequelize.define('carteItem', {
id: {
type: Sequelize.STRING,
allowNull: false,
primaryKey: true,
},
quantity: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
module.exports = CarteItem;
the problem occurs when I attend to Post a product to a cart using
exports.postCart = (req, res, next) => {
const prodId = req.body.productId;
let fetchedCart;
let newQuantity = 1;
req.user
.getCart()
.then((cart) => {
fetchedCart = cart;
return cart.getProducts({ where: { id: prodId } });
})
.then((products) => {
let product;
if (products > 0) product = products[0];
return Product.findByPk(prodId);
})
.then((product) => {
console.log(product);
return fetchedCart.addProduct(product, {
through: { quantity: newQuantity },
});
})
.then(() => {
res.redirect('/');
})
.catch((err) => console.log(err));
};
and I get this error
Executing (default): SELECT `id`, `quantity`, `createdAt`, `updatedAt`, `cartId`, `productId` FROM `carteItems` AS `carteItem` WHERE `carteItem`.`cartId` = '1' AND `carteItem`.`productId` IN ('7c64a81f-59d3-427d-af2a-f9c9ee6e4fde');
AggregateError
at recursiveBulkCreate (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/model.js:2600:17)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Function.bulkCreate (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/model.js:2837:12)
at async Promise.all (index 0)
at async BelongsToMany.add (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/associations/belongs-to-many.js:740:30) {
errors: [
BulkRecordError [SequelizeBulkRecordError]: notNull Violation: carteItem.id cannot be null
at /home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/model.js:2594:25
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 0)
at async recursiveBulkCreate (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/model.js:2590:9)
at async Function.bulkCreate (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/model.js:2837:12)
at async Promise.all (index 0)
at async BelongsToMany.add (/home/horus/Documents/WorkStation/learningPath/learningPathNode/node-complete-course/node_modules/sequelize/lib/associations/belongs-to-many.js:740:30) {
errors: [ValidationError],
record: [carteItem]
}
]
}
My problem was using the wrong definition of CartItem Schema, should be autoIncremented

Sequelize - is it possible to limit the number of record in junction table

There are 3 tables student_teacher, student, teacher with below relationship.
Each teacher will be responsible for 5 students, so the relationship should be 1 to Many, but I decide to create a junction table for storing extra information for this relationship.
When I create a student_teacher record, the payload will be like this:
{
"studentId": "xxx",
"teacherId": "yyy",
"groupName": "Group A"
}
Let's say I have record below now in table student_teacher:
[
{
"studentId": "studentA",
"teacherId": "teacherA",
"groupName": "Group X"
},
{
"studentId": "studentB",
"teacherId": "teacherA",
"groupName": "Group X"
},
{
"studentId": "studentC",
"teacherId": "teacherA",
"groupName": "Group X"
},
{
"studentId": "studentD",
"teacherId": "teacherA",
"groupName": "Group X"
},
{
"studentId": "studentE",
"teacherId": "teacherA",
"groupName": "Group X"
}
]
There are already 5 record for teacherA in table student_teacher, I will to forbid to create 1 more record for teacherA.
Is it possible to do it in Sequelize? Or handle I need to handle it in node.js function?
student-teacher.model.js
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const studentTeacher = sequelizeClient.define('student_teacher', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
studentId: {
allowNull: false,
type: DataTypes.UUID,
references: { model: 'student', key: 'id' },
defaultValue: Sequelize.UUIDV4,
unique: 'studentId_foreign_idx'
},
teacherId: {
allowNull: false,
type: DataTypes.UUID,
references: { model: 'teacher', key: 'id' },
defaultValue: Sequelize.UUIDV4,
unique: 'teacherId_foreign_idx'
},
groupName: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ''
},
...
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
studentTeacher.associate = function (models) {};
return studentTeacher;
};
student.model.js
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const student = sequelizeClient.define('student', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
email: {
type: DataTypes.STRING,
allowNull: false,
isEmail: true,
unique: 'email'
},
firstName:{
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
},
lastName:{
type: DataTypes.STRING,
allowNull: false,
defaultValue: '',
}
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
student.associate = function (models) {
student.belongsToMany(models.teacher, { as: 'teachers', through: 'student_teacher', foreignKey: 'studentId', onDelete: 'cascade' })
};
return student;
};
teacher.model.js
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const teacher = sequelizeClient.define('teacher', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
},
email: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
teacher.associate = function (models) {
teacher.belongsToMany(models.student, { as: 'students', through: 'student_teacher', foreignKey: 'teacherId', onDelete: 'cascade' })
};
return teacher;
};
Sequelize's hooks are very compatible with your requirement:
// in your student-teacher.model.js model (before you return the model)
studentTeacher.beforeCreate(async (instance, options) => {
try {
const result = await studentTeacher.findAll({
where: {
teacherId: instance.teacherId
}
});
if(result.length === MAX_RECORDS_FOR_TEACHER) {
throw new Error(`Cannot create more instnaces for ${instance.teacherId}`);
}
}
catch(e) {
throw e; // You must throw an error inside the hook in order to cancel
// the real statement execution.
}
});
Read more: https://sequelize.org/master/manual/hooks.html

sequelize many to many not working correcttly with a legacy databse

I've got an existing mysql database where i've got the following tables : category,product and product_category.I've used sequelizer-auto package to generate models from the 3 tables like the following:
Product.js ,model generated from product table:
module.exports = function(sequelize, DataTypes) {
const Product= sequelize.define('product', {
productId: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'product_id'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'name'
},
description: {
type: DataTypes.STRING(1000),
allowNull: false,
field: 'description'
},
price: {
type: DataTypes.DECIMAL,
allowNull: false,
field: 'price'
},
discountedPrice: {
type: DataTypes.DECIMAL,
allowNull: false,
defaultValue: '0.00',
field: 'discounted_price'
},
image: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'image'
},
image2: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'image_2'
},
thumbnail: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'thumbnail'
},
display: {
type: DataTypes.INTEGER(6),
allowNull: false,
defaultValue: '0',
field: 'display'
}
}, {
tableName: 'product'
});
Product.associate=(models)=>{
Product.belongsToMany(models.category,{
through:'product_category',
foreignkey:'product_id',
as:'categories'
})
}
return Product;
};
Category.js generated from 'category table'
module.exports = function(sequelize, DataTypes) {
const Category= sequelize.define('category', {
categoryId: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'category_id'
},
departmentId: {
type: DataTypes.INTEGER(11),
allowNull: false,
field: 'department_id'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'name'
},
description: {
type: DataTypes.STRING(1000),
allowNull: true,
field: 'description'
}
},
{
tableName: 'category',
});
Category.associate=(models)=>{
Category.belongsToMany(models.Product, {
through: 'product_category',
foreignkey: 'category_id',
as: 'products'
});
}
return Category;
};
ProductCategory from product_category table
module.exports = function(sequelize, DataTypes) {
return sequelize.define('product_category', {
productId: {
type: DataTypes.INTEGER(11),
references:{
key:'product_id',
model:'product'
}
},
categoryId: {
type: DataTypes.INTEGER(11),
references:{
key: 'category_id',
model:'category'
}
}
}, {
tableName: 'product_category'
});
};
And here is the category controller categories.js:
const db=require('../services/db_init');
const DataTypes=require('sequelize').DataTypes;
const Category=require('../database/models/Category')(db,DataTypes);
const Product=require('../database/models/Product')(db,DataTypes);
const {category_errors:{cat_01,cat_02}} = require('../services/errors.js');
//test code
const Product = require('../database/models/Product')(db,DataTypes);
module.exports=(app)=>{
app.get('/categories',async(req,res)=>{
try {
const categories = await Category.findAll({
include:{
model:Product,
as:'products'
}
});
return res.send(categories).status(200);
} catch (err) {
return res.json({error:err}).status(400);
}
});
app.get('/categories/:id',async(req,res)=>{
const id=req.params.id;
//checking if the id is a number
if(isNaN(id)){
return res.json({error:cat_01})//error returned
}
try {
const category=await Category.findByPk(id);
if(category){
return res.send(category).status(200);
}
return res.json({error:cat_02}).status(404);
} catch (err) {
return res.json(err).status(400);
}
});
}
All methode are working as expected,but after adding relashionship between models i've got some problems.First in GET /categories ,the implementation of the query was const categories = await Category.findAll() and everything was working fine,but after changing the implementation to const categories = await Category.findAll({include:{model:Product,as:'products'}}); i get the follwing error {
"error": {
"name": "SequelizeEagerLoadingError"
}
}
I've tried to read many topics,and solutions but i always have the same issue

Unable to insert id into a table that belongs to a foreign key referenced table using Sequelize

I am building serverless application using node js and using claudia-api-builder as a framework to launch APIs in AWS.
In app.js file, i call the required api as
const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();
module.exports = api;
api.post('/api/auth/validatephonenumber', async function (request)
{
return new Promise((resolve, reject) => {
index.loadDatabase().then((db) => {
resolve(loginController.validatePhonenumber(db, request));
});
});
});
Below is my code:
async function validatePhonenumber(db, request) {
return new Promise(
async (resolve, reject) => {
let emailid;
await db.EmailRegistration.sync().then(function () {
emailid = db.EmailRegistration.findOne({
where: { email: { [Op.eq]: mailid } },
attributes: ['id'],
});
});
if (emailid != null) {
console.log(`email id: ${emailid.id}`);
await db.ContactDetails.sync().then(function () {
db.ContactDetails.findOrCreate({
where: { contactnumber: phnum },
defaults: { EmailRegistrationId: emailid.id },
}).spread((contactdetails, created) => {
console.log(`contactdetails: ${contactdetails}`);
if (contactdetails !== null) {
resolve({ statuscode: indexController.statusCode.statusOK, contactdetails: contactdetails })
} else {
reject({ statuscode: indexController.statusCode.InternalServerError, message: 'phone number not created' });
}
});
});
};
});
}
I am trying to add a emailregistrationid of EmailRegistration table into ContactDetails table as a foreign key reference. I am using sequelize with mysql, nodejs to achieve the desired results. But, i am getting below error:
Unhandled rejection SequelizeForeignKeyConstraintError: Cannot add or update a child row: a foreign key constraint fails (inmeeydb.ContactDetails, CONSTRAINT ContactDetails_ibfk_1 FOREIGN KEY (EmailRegistrationId) REFERENCES EmailRegistration (id) ON DELETE CASCADE ON UPDATE CASCADE)
Below is my EmailRegistration models file:
const moment = require('moment');
module.exports = (sequelize, DataTypes) => {
const EmailRegistration = sequelize.define(
'EmailRegistration',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
email: {
type: DataTypes.STRING(50),
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: { min: 6 },
},
createdAt: {
type: DataTypes.DATE,
get() {
return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
},
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: null,
},
},
{
freezeTableName: true,
}
);
EmailRegistration.associate = function (models) {
EmailRegistration.hasOne(models.ContactDetails,
{ foreignKey: 'EmailRegistrationId' }
);
};
return EmailRegistration;
};
Below is my Contactdetails models file:
const moment = require('moment');
module.exports = (sequelize, DataTypes) => {
const ContactDetails = sequelize.define(
'ContactDetails',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
contactnumber: { type: DataTypes.STRING(13), allowNull: false },
isverified: { type: DataTypes.BOOLEAN, defaultValue: false },
createdAt: {
type: DataTypes.DATE,
get() {
return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
},
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: null,
},
},
{
indexes: [{ fields: ['contactnumber'], unique: true }],
},
{
freezeTableName: true,
}
);
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration, {
onDelete: 'CASCADE',
hooks: true,
foreignKey: { allowNull: false },
});
};
return ContactDetails;
};
I tried to change the code as below with reference in both tables, but nothing worked.
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration,
{ foreignKey: 'EmailRegistrationId' }
);
};
Not able to analyze how to overcome the issue. This worked fine when i used nodejs with expressjs and had no issues. It fails to identify the EmailRegistrationId(that is missing in the query) in ContactDetails table and shows the output as
INSERT INTO `ContactDetails` (`id`,`contactnumber`,`isverified`,`createdAt`,`updatedAt`) VALUES ('52974e07-8489-4101-ab71-6af874903290','+xxxxxxxxx',false,'2018-10-12 08:55:35','2018-10-12 08:55:35');
You need to update the configuration of your association. The ContactDetails model will now have a field called emailregistrationid
EmailRegistration.associate = function (models) {
EmailRegistration.hasMany(models.ContactDetails);
};
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration, {
onDelete: 'CASCADE',
hooks: true,
foreignKey: {
name: 'emailregistrationid'
allowNull: false
},
});
}
ContactDetails.create({
...
emailregistrationid: <some_valid_emailregistrationid>
})