How to use Sequelize belongsTo - node.js

I have simple sequelize models like below.
// user.js
module.exports = function(sequelize, DataTypes) {
const user = sequelize.define(
"User",
{
name: {
field: "name",
type: DataTypes.STRING(50),
unique: true,
allowNull: false
},
uid: {
field: "uid",
type: DataTypes.STRING(50),
allowNull: false
}
},
{
freezeTableName: true,
tableName: "user"
}
);
user.associate = function(models) {
user.hasMany(models.friend, {
foreignKey: "uid"
});
};
return user;
};
And there is another model.
// friend.js
module.exports = function(sequelize, DataTypes) {
const friend = sequelize.define(
"Friend",
{
uid: {
field: "uid",
type: DataTypes.STRING(50),
allowNull: false
},
jsonId: {
field: "json-id",
type: DataTypes.STRING(50),
allowNull: true
},
nlpId: {
field: "nlp-id",
type: DataTypes.STRING(50),
allowNull: true
}
},
{
freezeTableName: true,
tableName: "friend"
}
);
friend.associate = function(models) {
friend.belongsTo(models.user, { foreignKey: "uid" });
};
return friend;
};
And there is index.js. When I run sequelize, it gives me an error like "Error: Friend.belongsTo called with something that's not a subclass of Sequelize.Model".
Could you recommend some advice for this problem? Thank you so much for reading it.
db.user = require('./user')(sequelize, Sequelize);
db.friend = require('./friend')(sequelize, Sequelize);

Write to the user model
User.associate = models => {
User.hasMany(models.Friend, {
as: 'friends',
foreignKey: 'userId'
});
};
Write to the friend model
Friend.associate = models => {
Friend.belongsTo(models.User, {
as: 'friend',
foreignKey: 'userId'
});
};

Related

Sequelize model field that I did not add

I have a user, role and their relation model, when I want to insert into the relation model I get this error:
error: column "userUserId" of relation "roles_users_relationships" does not exist.
Can you help with this error?
(sorry if I wrote something wrong, this is my first question on )
This is how my model looks
Role model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles", {
role_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsToMany(models.users, {
through: "roles_users_relationship",
foreignKey: "role_id",
});
};
return table;
};
Users model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"users", {
user_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: true,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsTo(models.roles, {
through: "roles_users_relationship",
foreignKey: "user_id",
});
};
return table;
};
Roles Users relationship model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles_users_relationship", {
user_id: {
type: DataTypes.UUID,
allowNull: false,
},
role_id: {
type: DataTypes.UUID,
allowNull: false,
},
}, {
timestamps: false
}
);
return table;
};
In your through table you should add options in related table field:
references: {
model: User,
key: 'user_id'
}
Otherwise sequelize will do it automatically, like adding foreign key column in this way tableNamePrimaryKeyColumn in your case its 'userUserId'

Node Sequelize Relational Challenge

I have three tables (all associated model classnames use PascalCase)
schools school_codes course
------ ------ ------
id (pk) code (pk) name
name school_id (fk) school_code (fk)
I'm trying to define sequelize relations, so that this Course lookup returns the associated School:
const courseWithSchool = await models.Course.findOne({
include: [{
model: models.School,
required: true,
}],
})
The mysql for this is very simple.
mysql> select c.*, s.* from courses c inner join school_codes sc on c.school_code = sc.code inner join schools s on s.id = sc.school_id;
How do I define the relations in sequelize models (without modifying existing schema)? Thanks!
Here are the model definitions I have:
schools.js
module.exports = (sequelize, DataTypes) => {
const School = sequelize.define('School', {
name: DataTypes.STRING,
}, { underscored: true, freezeTableName: true, tableName: 'schools' })
return School
}
course.js
module.exports = (sequelize, DataTypes) => {
const Course = sequelize.define('Course', {
id: {
type: DataTypes.STRING,
primaryKey: true,
},
name: DataTypes.STRING,
school_code: {
type: DataTypes.STRING,
references: {
model: 'school_codes',
key: 'code',
}
}
}, { underscored: true, freezeTableName: true, tableName: 'courses' })
return Course
}
schoolcode.js
module.exports = (sequelize, DataTypes) => {
const SchoolCode = sequelize.define('SchoolCode', {
code:{
type: DataTypes.STRING,
primaryKey: true,
references: {
model: 'courses',
key: 'school_code'
}
},
school_id: {
type: DataTypes.INTEGER,
references: {
model: 'schools',
key: 'id',
},
},
}, { underscored: true, freezeTableName: true, tableName: 'school_codes', })
return SchoolCode
}
I'm just looking for the relations to add to the bottom of each model definition - example...
// School.associate = function (models) {
// School.belongsToMany(models.Course, {
// through: 'school_codes',
// foreignKey: 'school_id',
// otherKey: 'code'
// })
// }
We can keep association in its respective model. I prefer to keep association in respective master table rather than mapping table. The idea is to associate source model to target model and its relationship in both direction. For example let us say source model School has one SchoolCode target model and its reverse relation
//school.model.js
module.exports = (sequelize, DataTypes) => {
const School = sequelize.define('school', {
name: DataTypes.STRING,
}, { underscored: true, freezeTableName: true, tableName: 'schools' })
School.associate = function ({SchoolCode, Course}) {
School.hasOne(SchoolCode, {
foreignKey: 'school_id',
})
SchoolCode.belongsTo(School, {foreignKey: 'school_id'})
School.belongsToMany(Course, { through: SchoolCode , foreignKey : 'school_id'}); //added new
}
return School;
}
//course.model.js
module.exports = (sequelize, DataTypes) => {
const Course = sequelize.define('course', {
id: {
type: DataTypes.STRING,
primaryKey: true,
},
name: DataTypes.STRING,
school_code: {
type: DataTypes.STRING,
references: {
model: 'school_codes',
key: 'code',
}
}
}, { underscored: true, freezeTableName: true, tableName: 'courses' })
Course.associate = function ({SchoolCode, School}) {
Course.hasMany(SchoolCode, {
foreignKey: 'code',
})
Course.belongsToMany(School, { through: SchoolCode, foreignKey : 'code'}); //added new
}
return Course;
}
Finally the third model of SchoolCode (Mapping table).
Note that we don't have to add a reference school_code. It is a primaryKey code of same table. We use references mainly to define the foreign keys, no need for reverse definition here.
Hence commented that part from code below.
module.exports = (sequelize, DataTypes) => {
const SchoolCode = sequelize.define('SchoolCode', {
code:{
type: DataTypes.STRING,
primaryKey: true,
// references: {
// model: 'courses',
// key: 'school_code'
// }
},
school_id: {
type: DataTypes.INTEGER,
references: {
model: 'school',
key: 'id',
},
},
}, { underscored: true, freezeTableName: true, tableName: 'school_codes', })
return SchoolCode
}
References : https://sequelize.org/master/manual/assocs.html
You can define relations like
SchoolCode.belongsTo(School, { foreignKey: 'school_id', targetKey: 'id' });
Course.belongsTo(SchoolCode, { foreignKey: 'school_code', targetKey: 'code' });

Retrieve sequelize rows through a many-to-many relationship table

I have two models Company and Contractor linked through a CompanyContractor relational table.
company.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Company = sequelize.define('Company', {
name: {
type: DataTypes.STRING(30),
allowNull: false,
unique: true
},
slug: {
type: DataTypes.STRING(30),
allowNull: false
},
description: DataTypes.STRING(200),
}, {});
Company.associate = function(models) {
Company.belongsToMany(models.Contractor, { through: 'CompanyContractor', as: 'contractors',foreignKey: 'companyId' });
};
return Company;
};
contractor.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Contractor = sequelize.define('Contractor', {
name: {
type: DataTypes.STRING(50),
allowNull: false
}
}, {});
Contractor.associate = function(models) {
Contractor.belongsToMany(models.Company, { through: 'CompanyContractor', as: 'contractors' });
};
return Contractor;
};
companyContractor.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const CompanyContractor = sequelize.define('CompanyContractor', {
companyId: {
type: DataTypes.INTEGER,
allowNull: false
},
contractorId: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
timestamps: false
});
return CompanyContractor;
};
Is there a way to Contractor.findAll() through companyId?
Contractor.findAll({
include: [{
model: Company,
through: {
attributes: ['companyId']
}
}]
});
From the documentation

Associate different models using sequelize?

Hi I am trying to associate my User model with login model and Question_details models.But if i am using the Question_details association then i am geeting eagerLodingError :user is not associated to login but if i am commenting it then it works fine so how can i associate it ?
But if i am associating with
User Model
module.exports = (sequelize, DataTypes) => {
var Users = sequelize.define('users', {
name: {
type: DataTypes.STRING(100)
}
phone: {
type: DataTypes.BIGINT,
unique: true
}
}, { freezeTableName: true });
Users.associate = function(models) {
Users.hasOne(models.login, {
foreignKey: 'user_id',
as: 'loginDetails'
});
};
Users.associate = function(models) {
Users.hasMany(models.customer_query, {
foreignKey: 'user_id',
as: 'queryDetails'
});
};
return Users;
};
LOGIN MODEL
module.exports = (sequelize, DataTypes) => {
var Login = sequelize.define('login', {
user_id: {
type: DataTypes.INTEGER
},
user_name: {
type: DataTypes.STRING(500),
isEmail: true
},
password: {
type: DataTypes.STRING(500)
},
role_id: {
type: DataTypes.INTEGER
}
}, {
underscored: true,
freezeTableName: true
});
Login.associate = function(models) {
Login.belongsTo(models.users, {
foreignKey: 'user_id',
onDelete: 'CASCADE'
});
};
Login.associate = function(models) {
Login.belongsTo(models.roles, {
foreignKey: 'role_id',
onDelete: 'CASCADE'
});
};
return Login;
};
questionDetails Model
module.exports = function(sequelize, DataTypes) {
var questionDetails = sequelize.define('question_details', {
query_id: {
type: DataTypes.INTEGER
},
ques_type_id: {
type: DataTypes.INTEGER
},
created_by: {
type: DataTypes.INTEGER
},
question: {
type: DataTypes.TEXT
},
}, { freezeTableName: true });
questionDetails.associate = function(models) {
questionDetails.belongsTo(models.users, {
foreignKey: 'created_by',
onDelete: 'CASCADE'
});
};
return questionDetails;
};
You only have to define associate once. When you define it the second time you're actually overwriting it. So for the User model you should actually do...
Users.associate = function(models) {
Users.hasOne(models.login, {
foreignKey: 'user_id',
as: 'loginDetails'
});
Users.hasMany(models.customer_query, {
foreignKey: 'user_id',
as: 'queryDetails'
});
};
Do similarly for your login model as you are also overwriting the associate function there.
Good luck! :)

Update with association using Sequelize.js

I am trying to update with association using sequelize.js.
I have tried give example on stackoverflow namely the following links:
Sequelize update with association
Sequelize update with association
Updating attributes in associated models using Sequelize
all of these links did not get me to the goal i am trying to accomplish.
My model is as follow, I have a country module and a city module. a country has many cities. please refer to the module bellow.
Please advise.
country.js file
module.exports = function (sequelize, DataTypes) {
var country= sequelize.define('COUNTRY', {
COUNTRY_ID: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
COUNTRY_NAME: DataTypes.STRING,
COUNTRY_CURRENCY: DataTypes.STRING
}, {
freezeTableName: true,
classMethods: {
associate: function (models) {
COUNTRY_ID.hasMany(models.CITIES, {
foreignKey: 'COUNTRY_ID'
})
}
},
instanceMethods: {
updateAssociation: function (onSuccess, onError) {
country.findAll({
where: {
COUNTRY_ID: req.params.country_id
},
include: [
{
model: sequelize.import('./cities.js'),
}
]
})
})
.then(country =>{
const updatePromises = country.map(countries =>{
return countries.updateAttributes(req.body);
});
const updatePromisescities = list.CITY.map(cities =>{
return cities.updateAttributes(req.body.CITYs[0]);
});
return sequelize.Promise.all([updatePromises, updatePromisescities ])
}).then(onSuccess).error(onError);
}
}
});
return country;
};
city.js file
module.exports = function (sequelize, DataTypes) {
var CITY = sequelize.define('LIST_CODE', {
CITY_ID: {
type: DataTypes.INTEGER,
primaryKey: true
},
COUNTRY_ID: {
type: DataTypes.INTEGER,
primaryKey: true
}
}, {
freezeTableName: true,
timestamps: false,
classMethods: {
associate: function (models) {
// associations can be defined here
CITY.belongsTo(models.COUNTRY, {
foreignKey: 'COUNTRY_ID'
})
}
}
});
return CITY;
};

Resources