问题
I have two tables. One is skills, another is ratings. My problem is specific to ratings: The model of ratings is:
var sequelize = require('../sequelizeConfig');
var Sequelize = require('sequelize');
var Ratings=sequelize.define('ratings',{
ratingID:{
type:Sequelize.BIGINT,
field:'rating_id',
primaryKey:true
},
empID:{
type: Sequelize.STRING,
field:'emp_id'
},
skillID:{
type:Sequelize.STRING,
field:'skill_id',
references: {
model: 'skills',
key: 'skill_id'
}
},
rating:{
type: Sequelize.BIGINT ,
field:'rating'
}
},{
tableName:'ratings',
freezeTableName: true
})
module.exports=Ratings;
In controller, i have below relation. I am unsure if use of hasOne is right. With only 'belongsTo' to state foreignkey relationship, i only got ratings is not associated to skills. Basically skill_id in ratings table has reference to skill_id in skills table.
var skillsets = require('../../models/skillsets');
var ratings = require('../../models/ratings');
skillsets.hasOne(ratings,{foreignKey:'skillID',sourceKey:'skillsetID'});
ratings.belongsTo(skillsets,{foreignKey:'skillID',targetKey:'skillsetID'});
I tried to query as below:
skillsets.findAll({
where:{
roleID: role
},
include:[{
model:ratings,
where:{
emp_id: empID
},
attributes:['rating'],
required:false
}]
})
Everything seem fine but this hasOne does something fishy. It generates query as:
SELECT "skills"."skill_id" AS "skillsetID", "skills"."role_id" AS "roleID", "skills"."field", "skills"."skill_name" AS "skillName", "rating"."rating_id" AS "rating.ratingID", "rating"."rating" AS "rating.rating" FROM "skills" AS "skills" LEFT OUTER JOIN "ratings" AS "rating" ON "skills"."skill_id" = "rating"."skill_id" AND "rating"."emp_id" = '12344' WHERE "skills"."role_id" = 'developer';
Due to "rating"."rating" AS "rating.rating" , result comes as below:
[
{
"skillsetID": "Angular",
"roleID": "developer",
"field": "Frontend",
"skillName": "Angular",
"rating":
{
"rating": "4"
}
}]
What i expect is just like:
[
{
"skillsetID": "Angular",
"roleID": "developer",
"field": "Frontend",
"skillName": "Angular",
"rating":4
}]
Could you please favour?
回答1:
This nesting of included model ratings is the default behavior in sequelize. You can pass in the option raw: true to get a result that looks like this:
{
"skillsetID": "Angular",
"roleID": "developer",
"field": "Frontend",
"skillName": "Angular",
"rating.rating": "4",
}
If you don't want the dot notation in the keys then you can change your sequelize query like this:
var sequelize = require('../sequelizeConfig');
skillsets.findAll({
attributes: {
include: [ // Include these attributes along with all other attributes
[
sequelize.literal('rating.rating'), // get `rating` from `ratings` table in the query
'rating', // use `rating` as alias
]
]
},
where: {
roleID: role
},
include: [
{
model: ratings,
where: {
emp_id: empID
},
attributes: [], // This tells sequelize to not nest any attributes inside ratings object
required: false
}
]
});
This will give you the required result:
{
"skillsetID": "Angular",
"roleID": "developer",
"field": "Frontend",
"skillName": "Angular",
"rating": "4",
}
hasOne and belongsTo:
The purpose of relations in sequelize is that they allow you to include related models when querying and make relations when creating tables. If you don't add a hasOne relation. Then sequelize will tell you that skills does not belong to rating even if there is a foreign key skillID inside the ratings table. hasOne tells sequelize that you can include the model ratings inside skills with a 1-1 relationship
来源:https://stackoverflow.com/questions/59107738/sequelize-foreignkey-relationship-problem-with-alias