Sequelize PostgresSQL - Column does not exist when it does - node.js

I do not understand why my api is calling this column and not courseSection.courseId. from postman
I am building my project using AngularJs, PostgresSQL, NodeJs and Sequelize ORM.
This is my part of my course.contorller.js:
const db = require("../models");
const Course = db.course;
//view course catalogue
exports.retrieveAll = (req, res) => {
Course.findAll({
include: [{
model: db.courseSection,
as: "courseSection"
}, {
model: db.category,
as: "category"
}]
})
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message: err.message
});
}); };
This is my course.model.js
module.exports = (sequelize, Sequelize) => {
const Course = sequelize.define(
"course",
{
courseId: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true,
},
},
description: {
type: Sequelize.STRING,
},
creditPrice: {
type: Sequelize.INTEGER,
},
isArchived: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
isDraft: {
type: Sequelize.BOOLEAN,
},
level: {
type: Sequelize.ENUM({
values: [
"PRIMARY 1",
"PRIMARY 2",
"PRIMARY 3",
"PRIMARY 4",
"PRIMARY 5",
"PRIMARY 6",
],
}),
},
createdAt: {
type: Sequelize.DATE,
},
updatedAt: {
type: Sequelize.DATE,
},
},
{
classMethods: {
associate: function (models) {
Course.hasMany(models.CourseSection, {
foreignKey: "courseId",
onDelete: "CASCADE",
});
Course.hasMany(models.Material, {
foreignKey: "courseId",
onDelete: "CASCADE",
});
Course.hasMany(models.Review, {
foreignKey: "courseId",
onDelete: "CASCADE",
});
Course.hasMany(models.Enrolment, {
foreignKey: "courseId",
onDelete: "CASCADE",
});
Course.belongsTo(models.Category, {
foreignKey: "categoryId",
onDelete: "CASCADE",
});
Course.belongsTo(models.User, {
foreignKey: "userId",
onDelete: "CASCADE",
});
},
},
}
);
return Course;
};
My courseSection.js
module.exports = (sequelize, Sequelize) => {
const CourseSection = sequelize.define(
"courseSection",
{
sectionId: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true,
},
},
isArchived: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
createdAt: {
type: Sequelize.DATE,
},
updatedAt: {
type: Sequelize.DATE,
},
},
{
classMethods: {
associate: function (models) {
CourseSection.belongsTo(models.Course, {
foreignKey: "courseId",
onDelete: "CASCADE",
});
},
},
}
);
return CourseSection;
};
My migration for course.js
"use strict";
//npx sequelize migration:generate --name course
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.createTable("course", {
courseId: {
allowNull: false,
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
categoryId: {
type: Sequelize.INTEGER,
onDelete: "CASCADE",
references: {
model: "category",
key: "categoryId",
},
},
userId: {
type: Sequelize.INTEGER,
onDelete: "CASCADE",
references: {
model: "user",
key: "userId",
},
},
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true,
},
},
description: {
type: Sequelize.STRING,
},
creditPrice: {
type: Sequelize.INTEGER,
},
isArchived: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
isDraft: {
type: Sequelize.BOOLEAN,
},
level: {
type: Sequelize.ENUM({
values: [
"PRIMARY 1",
"PRIMARY 2",
"PRIMARY 3",
"PRIMARY 4",
"PRIMARY 5",
"PRIMARY 6",
],
}),
},
createdAt: {
type: Sequelize.DATE,
},
updatedAt: {
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
return queryInterface.dropTable("course");
},
};
My migration for courseSection
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.createTable("courseSection", {
sectionId: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true,
},
},
courseId: {
type: Sequelize.INTEGER,
onDelete: "CASCADE",
references: {
model: "course",
key: "courseId",
},
},
isArchived: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
createdAt: {
type: Sequelize.DATE,
},
updatedAt: {
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
return queryInterface.dropTable("courseSection");
},
};
My index.js in /model
my postgres table:
When I do localhost:3000/courses/course, my vscode shows the following error:
Executing (default): SELECT "course"."courseId", "course"."name", "course"."description", "course"."creditPrice", "course"."isArchived", "course"."isDraft", "course"."level", "course"."createdAt", "course"."updatedAt", "course"."categoryCategoryId", "course"."categoryId", "course"."userId", "course"."userUserId", "courseSection"."sectionId" AS "courseSection.sectionId", "courseSection"."name" AS "courseSection.name", "courseSection"."isArchived" AS "courseSection.isArchived", "courseSection"."createdAt" AS "courseSection.createdAt", "courseSection"."updatedAt" AS "courseSection.updatedAt", "courseSection"."courseCourseId" AS "courseSection.courseCourseId", "courseSection"."courseId" AS "courseSection.courseId", "category"."categoryId" AS "category.categoryId", "category"."isArchived" AS "category.isArchived", "category"."name" AS "category.name", "category"."createdAt" AS "category.createdAt", "category"."updatedAt" AS "category.updatedAt" FROM "course" AS "course" LEFT OUTER JOIN "courseSection" AS "courseSection" ON "course"."courseId" = "courseSection"."courseCourseId" LEFT OUTER JOIN "category" AS "category" ON "course"."categoryId" = "category"."categoryId";
I have been on this problem for the past 2 days and I honestly do not know where I went wrong. I hope anyone can help me please.

You defined associations between courseSection and course twice:
in associate methods of a model classes (correct ones)
in index.js without indicating foreignKey option
I suppose you just need to remove associations in index.js and just call associate methods of models in index.js.
Something like
db.category.associate(db.models);
// and so on

Related

postgres returns another table column while inserting data in sequelize

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

Sequelize addConstraint syntax

Im trying to add two tables, Playlist and Label.
Label optionally has a playlist, many playlists can relate to the same label.
In order to add the foreign key constraint to playlist im trying to add it using addConstraint.
The docs are terrible on this .
This is what i have:
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Playlist", {
id: { type: Sequelize.STRING, primaryKey: true, allowNull: false },
track_uri: Sequelize.STRING,
track: Sequelize.STRING(150),
artist: Sequelize.STRING(150),
added_at: {
type: Sequelize.DATE,
defaultValue: new Date(),
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
defaultValue: new Date(),
allowNull: false,
},
is_album_track: Sequelize.BOOLEAN,
label: { type: Sequelize.STRING, unique: true },
});
await queryInterface.createTable("Label", {
id: { type: Sequelize.STRING, primaryKey: true },
playlist_link: {
type: Sequelize.STRING(150),
unique: true,
allowNull: false,
},
password: { type: Sequelize.STRING, allowNull: false },
email: { type: Sequelize.STRING, allowNull: false },
playlist: {
type: Sequelize.STRING,
foreignKey: true,
references: {
model: "Playlist",
label: "id",
},
},
});
await queryInterface.addConstraint("Playlist", {
type: "foreign key",
fields: ["label"],
name: "label_fkey",
references: {
table: "Label",
field: "id",
},
onDelete: "cascade",
onUpdate: "cascade",
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Label");
await queryInterface.dropTable("Playlist");
},
};
Im getting this error:
ERROR: column "label" referenced in foreign key constraint does not exist

Sequelize foreign key with association

I have a database that was created with Postgres that was set up for a single foreign key association, Now, this would be mapped as a role table model
consider I have two tables user and roles
roles contain role details and user contain user details of role
const uuid = require('uuid/v4');
('use strict');
module.exports = (sequelize, DataTypes) => {
const role = sequelize.define(
'role',
{
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{}
);
role.beforeCreate((role) => (role.id = uuid()));
role.associate = function (models) {
role.hasMany(models.user), { foreignKey: 'roleId', as: 'user_roleId' };
};
return role;
};
role migration
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('roles', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
},
name: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('roles');
},
};
user model
const uuid = require('uuid/v4');
('use strict');
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define(
'user',
{
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: DataTypes.STRING,
email: {
type: DataTypes.STRING,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
phoneNumber: {
type: DataTypes.STRING,
},
roleId: {
type: DataTypes.UUID,
},
},
{
timestamps: true,
paranoid: true,
defaultScope: {
attributes: { exclude: ['password'] },
},
}
);
user.beforeCreate((user) => (user.id = uuid()));
user.associate = function (models) {
user.belongsTo(models.role, { foreignKey: 'roleId', onDelete: 'CASCADE' });
};
return user;
};
user migration
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('users', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
},
firstName: {
type: Sequelize.STRING,
},
lastName: {
type: Sequelize.STRING,
},
email: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
},
phoneNumber: {
type: Sequelize.STRING,
},
roleId: {
type: Sequelize.UUID,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
deletedAt: {
allowNull: true,
type: Sequelize.DATE,
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('users');
},
};
after running the migration these tables are created in my database.role_id is also present in the user table. but role_id is not generated as a foreign key in my user table. also please verify that the relationship which is mention here(one to many) is correct or not.
please verify my code and give me any suggestions if any changes required. I'm new in development
Your user migration also needs to know about the foreign key; you do this by adding a references: key to the column definition. The Sequelize documentation has a foreign key example; scroll about half way down the page (or just search for references).
In your case the user migration should look something like:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('users', {
// ... other fields omitted
roleId: {
type: Sequelize.UUID,
references: {
model: { tableName: 'role' }
key: 'id',
},
},
// ... more fields omitted
});
},
// down: omitted
}

Cyclic dependency found

I have the following error:
Unhandled rejection Error: Cyclic dependency found. coupons is
dependent of itself. Dependency chain: coupons -> orders => coupons
My order.js model looks like as follows:
'use strict';
module.exports = (sequelize, DataTypes) =>
{
var Order = sequelize.define('orders',
{
id:
{
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
userid:
{
type: DataTypes.INTEGER,
references:
{
model: 'users',
key: 'id'
}
},
coupon_id:
{
type: DataTypes.INTEGER,
allowNull: true,
references:
{
model: 'coupons',
key: 'id'
},
},
product:
{
type: DataTypes.INTEGER,
references:
{
model: 'products',
key: 'id'
}
},
address:
{
type: DataTypes.INTEGER,
references:
{
model: 'address',
key: 'id'
}
},
canceled:
{
type: DataTypes.INTEGER,
defaultValue: 0
},
quantity:
{
type: DataTypes.INTEGER,
},
note:
{
allowNull: true,
type: DataTypes.STRING
},
},
{
freezeTableName: true,
tableName: 'orders',
createdAt: 'createdat',
updatedAt: 'updatedat',
});
Order.associate = models => {
Order.hasMany(models.coupons, {
foreignKey: 'id',
onDelete: 'cascade',
onUpdate: 'cascade',
constrains: false
});
};
return Order;
};
and coupon.js looks like this:
'use strict';
module.exports = (sequelize, DataTypes) =>
{
var Coupon = sequelize.define('coupons',
{
id:
{
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name:
{
type: DataTypes.STRING
},
code:
{
type: DataTypes.STRING
},
discount:
{
type: DataTypes.FLOAT
},
expires:
{
type: 'TIMESTAMP',
},
created_by:
{
type: DataTypes.INTEGER,
references:
{
model: 'users',
key: 'id'
},
},
maxuse:
{
type: DataTypes.INTEGER,
},
},
{
freezeTableName: true,
tableName: 'coupons',
createdAt: 'createdat',
updatedAt: 'updatedat'
});
Coupon.associate = models => {
Coupon.belongsTo(models.orders,
{
foreignKey: 'id',
onDelete: 'cascade',
onUpdate: 'cascade',
});
};
return Coupon;
};
It seems that I am doing something wrong with the associations. Any help would be appreciated.
NOTE: Everytime I comment out coupon_id: on orders.js, the error goes out. Still, I need this functionality.

Sequelizejs is not associated to

I made some associate but it did not work, probably with me that something is wrong, ask for help.
There are two models
module.exports = function (sequelize, DataTypes) {
var pages_lang = require('./pages_lang')(sequelize, DataTypes);
return sequelize.define('pages', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true,
references : { model: "pages_lang", key: "page_id" }
},
name: {
type: DataTypes.STRING,
allowNull: false
},
published: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: '0'
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: '0000-00-00 00:00:00'
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: '0000-00-00 00:00:00'
}
}, {
classMethods: {
associate: function (models) {
this.hasMany(models.pages_lang, {onDelete: 'SET NULL', onUpdate: 'CASCADE', foreignKey: 'page_id', as: 'pages', through: models.pages_lang});
},
getAll() {
return this.findAll({include: [{model: pages_lang, as: 'pages_lang'}]}).then(function (result) {
return result;
});
}
}
});
};
module.exports = function (sequelize, DataTypes) {
return sequelize.define('pages_lang', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
page_id: {
type: DataTypes.INTEGER(10),
allowNull: false,
references : { model: "pages", key: "id" }
},
content: {
type: DataTypes.TEXT,
allowNull: false
}
}, {
classMethods: {
associate: function (models) {
this.belongsTo(models.pages, {foreignKey: 'id', foreignKeyConstraint:true, as: 'pages', through: models.pages});
}
}
});
};
But when you call results in an error
Unhandled rejection Error: pages_lang (pages_lang) is not associated
to pages!
Advance very grateful for the help
Your association alias (as) should match what you pass to findAll
this.hasMany(models.pages_lang, {onDelete: 'SET NULL', onUpdate: 'CASCADE', foreignKey: 'page_id', as: 'pages_lang' });
return this.findAll({include: [{model: pages_lang, as: 'pages_lang'}]});
Since the model is already called pages_lang, you can also skip the alias completely:
this.hasMany(models.pages_lang, {onDelete: 'SET NULL', onUpdate: 'CASCADE', foreignKey: 'page_id'});
return this.findAll({include: [pages_lang]});
Notice that I removed the through argument - it should only be used for belongsToMany (many-to-many)

Resources