sequelize selecting columns that are not mentioned in the model - node.js

I have 2 tables that are in a 1 to many relationship (course has many subjects), and before doing a delete operation on subject I want to check if it is associated with any course, so here are my models:
Course:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Course = sequelize.define('Course', {
name: DataTypes.STRING,
desc: DataTypes.TEXT
}, {});
Course.associate = function(models) {
Course.belongsToMany(models.Subject, {
through: 'courseSubjects'
});
Course.hasMany(models.Batch)
};
return Course;
};
and subject:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Subject = sequelize.define('Subject', {
name: DataTypes.STRING,
desc: DataTypes.TEXT
}, {});
Subject.associate = function(models) {
Subject.belongsToMany(models.Module, {
through: 'subjectModules'
});
Subject.belongsToMany(models.Course, {
through: 'courseSubjects',
});
};
return Subject;
};
So this is the statement I am calling:
res.status(200).send(subject.getCourses())
and getting error:
Executing (default): SELECT Course.id, Course.name, Course.desc, Course.createdAt, Course.updatedAt, Course.courseId, courseSubjects.createdAt AS courseSubjects.createdAt, courseSubjects.updatedAt AS courseSubjects.updatedAt, courseSubjects.CourseId AS courseSubjects.CourseId, courseSubjects.SubjectId AS courseSubjects.SubjectId FROM Courses AS Course INNER JOIN courseSubjects AS courseSubjects ON Course.id = courseSubjects.CourseId AND courseSubjects.SubjectId = 34;
[0] Unhandled rejection SequelizeDatabaseError: Unknown column 'Course.courseId' in 'field list'
I do not understand why is it trying to select 'courseId'.. Please help me resolve this.

You need to add relation into course table as well, it will remove the 'courseId' column from select.

Related

Sequelize trying to SELECT a column which doesn't exist of a join table

I'm having trouble querying a join table. I use, for example, the findAll() Model method. It gives me this error
code:
const { UserItems, sequelize } = require('./dbObjects');
const { Op } = require('sequelize');
async function run() {
const userItem = await UserItems.findAll();
console.log(user);
}
run();
error:
at async Function.findAll (E:\1dsktp\bot\node_modules\sequelize\dist\lib\model.js:1119:21)
at async run (E:\1dsktp\bot\dbTesting.js:14:15) {
name: 'SequelizeDatabaseError',
parent: [Error: SQLITE_ERROR: no such column: id] {
errno: 1,
code: 'SQLITE_ERROR',
sql: 'SELECT `id`, `amount` FROM `userItems` AS `userItems`;'
},
original: [Error: SQLITE_ERROR: no such column: id] {
errno: 1,
code: 'SQLITE_ERROR',
sql: 'SELECT `id`, `amount` FROM `userItems` AS `userItems`;'
},
sql: 'SELECT `id`, `amount` FROM `userItems` AS `userItems`;',
parameters: {}
}
For some reason, It's trying to look for a column named 'id', which of course doesn't exist.
My db is pretty simple, it consists of 3 tables, one being a join table:
User
Item
UserItems (join table and the one I'm having trouble with)
UserItems has two foreign keys, which are userId from User and itemId from Item. These were added associating both tables with the belongsToMany() method.
User.belongsToMany(Item, { through: UserItems, foreignKey: 'userId' });
Item.belongsToMany(User, { through: UserItems, foreignKey: 'itemId' });
Here is a picture of what the UserItems table looks like (I'm using SQLiteStudio for this)
Here is the UserItems model
module.exports = (sequelize, DataTypes) => {
const model = sequelize.define('userItems', {
amount: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false,
},
}, {
timestamps: false,
});
return model;
};
Obviously, you need to add a primary key column for UserItems (both in a table and in a model) because Sequelize does not support composite primary and foreign keys and by default, it suggests you have id as a primary key if you don't define any primary key explicitly.

Sequelize doesn't read the new modelname after I do refactor (remove s in end modelname)

I've a backend app built in Express with Sequelize ORM.
Here is my code;
user.js (model)
'use strict';
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('user', {
username: DataTypes.STRING,
}, {
// tableName: 'user'
});
user.associate = function(models) {
// associations can be defined here
};
return user;
};
user.js (controller):
const User = require('../models').user;
module.exports = {
getUser: function (req, res) {
User.findAll().then(value => {
res.json(value);
})
}
}
When I start the project, it return error Unhandled rejection SequelizeDatabaseError: relation "users" does not exist. As you can see my code above, I've set the model as user not users, and the table in db also user not users. It's only work fine if I add the tableName: 'user' in the model file.
NOTE: By the default, when I do create model with sequelize, the file name and model define is users, but I refactor file name and define inside model into user
Why does this happen?
This is default behavior - Sequelize automatically transforms model name to plural. In order to disable that you should freeze table name in model definition (or just set table name explicitly like you are actually doing):
freezeTableName: true,

Problem with Sequelize and specifying foreign key in an association

I have placements that belong to an App. The foreign_key on the placements table is appId (not AppId). I have specified as follows but get the error:
Unhandled rejection SequelizeDatabaseError: column Placements.AppId does not exist
My Placement Model:
'use strict';
const App = require('./').App
module.exports = (sequelize, DataTypes) => {
const Placement = sequelize.define('Placement', {
name: DataTypes.STRING,
isActive: DataTypes.BOOLEAN,
}, {
tableName: 'placements'
});
Placement.associate = function(models) {
Placement.belongsTo(models.App, { foreignKey: 'appId'})
// associations can be defined here
};
return Placement;
};
How do I tell Sequelize that the foreignKey is appId and not AppId?
Hmm... I don't see nothing wrong with your code. Which version of Sequelize are you using?
Just a couple of non-related comments:
You don't need to import App, it is already in models object.
I think you don't need tableName parameter either.
Try to use the field property
Placement.belongsTo(models.App, {
foreignKey: {
name: 'AppId',
field: 'appId'
}
}
)
You need to have the AppId columns present in App model. Explicitly passing { foreignKey: 'appId'}) to belongsTo makes Sequelize use the key as it is.
So you need to create an App model which has -
const App = sequelize.define('App', {
AppId: DataTypes.INTEGER,
..
}, {
tableName: 'App'
});
Another options would be to change this
Placement.belongsTo(models.App, { foreignKey: 'appId'})
to
Placement.belongsTo(models.App)
This way Sequelize automatically handles all relations between the models.

Sequelize self reference canĀ“t make a join

I'm trying to make a many to many table with matches of different teams and it works, but when I tried to make a join I got this error:
Unhandled rejection Error: team is not associated to match!
Here is my code:
var Sequelize = require('sequelize');
var sequelize = new Sequelize('cricket', 'root', '');
var Team = sequelize.define('team', {
name: Sequelize.STRING,
});
var Match = sequelize.define('match', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
scoreHome: Sequelize.INTEGER,
scoreAway: Sequelize.INTEGER,
});
Team.belongsToMany(Team, {as: 'Home', through: Match, foreignKey: 'homeTeamId'});
Team.belongsToMany(Team, {as: 'Away', through: Match, foreignKey: 'awayTeamId'});
sequelize.sync().then(function () {
Match.findAll({
include: [ Team ]
}).then(function (matches) {
console.log(matches)
});
});
You also need to provide the reverse relationship for Match.
In your current setup Team is associated with Team, not with Match. Match model is your through model.
For example valid association for Match would be :
var HomeTeam = Match.belongsTo( Team, { as: 'HomeTeam', foreignKey: 'homeTeamId' });
var AwayTeam = Match.belongsTo( Team, { as: 'AwayTeam', foreignKey: 'awayTeamId' })
sequelize.sync().then(function () {
Match.findAll({
include: [ HomeTeam, AwayTeam ]
}).then(function (matches) {
console.log(matches)
});
});
// Makes the following query
// SELECT `match`.`id`, `match`.`scoreHome`, `match`.`scoreAway`, `match`.`createdAt`, `match`.`updatedAt`, `match`.`homeTeamId`, `match`.`awayTeamId`, `HomeTeam`.`id`
// AS `HomeTeam.id`, `HomeTeam`.`name` AS `HomeTeam.name`, `HomeTeam`.`createdAt`
// AS `HomeTeam.createdAt`, `HomeTeam`.`updatedAt` AS `HomeTeam.updatedAt`, `AwayTeam`.`id` AS `AwayTeam.id`, `AwayTeam`.`name` AS `AwayTeam.name`, `AwayTeam`.`createdAt` AS `AwayTeam.createdAt`, `AwayTeam`.`updatedAt` AS `AwayTeam.updatedAt` FROM `matches` AS `match` LEFT OUTER JOIN `teams` AS `HomeTeam` ON `match`.`homeTeamId` = `HomeTeam`.`id` LEFT OUTER JOIN `teams` AS `AwayTeam` ON `match`.`awayTeamId` = `AwayTeam`.`id`

Try to create HABTM connection Sequelize.js

I'm trying to create a HABTM relationship with Sequelize but I can't get it done.... I still receive an error message:
return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1
^
TypeError: Cannot call method 'toLowerCase' of undefined
I have a User model, a Book model and an UserBooks model. And ofcourse my database contains a "users" table, "user_books" table and "books" table.
UserBooks model:
module.exports = function(schema, DataTypes) {
var UserBooks = schema.define('UserBooks', {
}, {
tableName: 'user_books', // this will define the table's name
timestamps: false // this will deactivate the timestamp columns
});
UserBooks.sync();
return UserBooks;
};
User model:
module.exports = function(schema, DataTypes) {
var User = schema.define('User', {
keywords: DataTypes.STRING
}, {
tableName: 'users', // this will define the table's name
timestamps: false ,// this will deactivate the timestamp columns
syncOnAssociation:false
});
User.hasMany(Book, { foreignKey: 'user_id', through: UserBooks });
User.sync();
return User;
};
Book model:
module.exports = function(schema, DataTypes) {
var Book = schema.define('Book', {
keywords: DataTypes.STRING
}, {
tableName: 'books', // this will define the table's name
timestamps: false ,// this will deactivate the timestamp columns
syncOnAssociation:false
});
Book.hasMany(User, { foreignKey: 'book_id', through: UserBooks });
Book.sync();
return Book;
};
In your User model you are trying to create an association with a model that is not defined in that scope. In User.js, you only have access to User, not Book or UserBooks which are undefined. Thats whats causing your error.
You can either create associations in the place where you import all your models into your app, or in the models file by importing the models you want to associate with (bevare of circular imports). Your user model could be changed to:
module.exports = function(schema, DataTypes) {
var Book = schema.import(__dirname + '/book');
var UserBooks = schema.import(__dirname + '/userbooks');
var User = schema.define('User', {
keywords: DataTypes.STRING
}, {
tableName: 'users', // this will define the table's name
timestamps: false ,// this will deactivate the timestamp columns
syncOnAssociation:false
});
User.hasMany(Book, { foreignKey: 'user_id', through: UserBooks });
Book.hasMany(User, { foreignKey: 'book_id', through: UserBooks });
return User;
};
For another example of how to do it, see http://sequelizejs.com/articles/express#minimal-express-app
Also, I've removed the call to User.sync from your code. Sync is an async call, while import is sync. This means that your are defining your model, starting to sync it to the DB, and then returning it, before you know that it has finished syncing. This means you could potentially be trying to work create instances with it before the table has been created. Instead, you should use sequelize.sync to sync all your models at once, and attach a callback to wait for the sync to finish (see the link I posted for a code example)

Resources