Dan*_*rra 5 postgresql node.js express sequelize.js
我在不同的论坛上多次看到这个问题,但一直无法解决。我正在使用 Express 和 PostgreSQL 以及 Sequelize。
基本上我有两个模型:校园和学术经理。两者是一对一的关系,Campus有一名学术经理。
我已经实现了两个模型和关联工作,我可以看到它显示在 postgres 服务器的 mi 数据库中。但是当我尝试实现校园的获取请求时,我尝试包含经理信息,但没有成功。我不断收到同样的错误:
SequelizeEagerLoadingError:academic_manager 未与校园关联!
我相信我的问题与包括有关
这是我的代码片段:
校园.js
const campus = (sequelize, DataTypes) =>{
const Campus = sequelize.define('campus', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
manager: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'academic_manager',
key: 'id'
}
}
});
Campus.associate = models => {
Campus.hasOne(models.Manager, { foreignKey: 'id'});
}
return Campus;
};
export default campus;
Run Code Online (Sandbox Code Playgroud)
学术管理器.js
const manager = (sequelize, DataTypes) =>{
const Manager = sequelize.define('academic_manager', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false
}
});
Manager.associate = models => {
Manager.belongsTo(models.Campus, { foreignKey: 'id'});
}
return Manager;
};
export default manager;
Run Code Online (Sandbox Code Playgroud)
以及获取方法:
router.get('/', async (req, res) => {
const campus = await req.context.models.Campus.findAll({
include: [
{ model: req.context.models.Manager }
]
});
return res.send(campus);
});
Run Code Online (Sandbox Code Playgroud)
get 请求无需包含即可工作。我知道关联已实现,因为当我描述我的校园表和我的经理表时,我有以下内容:
TABLE "campus" CONSTRAINT "campus_manager_fkey" FOREIGN KEY (manager) REFERENCES academic_manager(id)
Run Code Online (Sandbox Code Playgroud)
您的模型定义有几个问题。Sequelize 可能会混淆您是否想要关联模型,或者只是让它们相互引用。
您添加了实现关系约束的关联,还添加了引用键,该引用键旨在允许引用但不允许实现约束。
可能想阅读:
我已经评论了你的代码:
const Campus = (sequelize, DataTypes) =>{
const Campus = sequelize.define('Campus', {
name: {
type: DataTypes.STRING,
allowNull: false,
}
// this is not correct.
// read when to use reference key further below
/* manager: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'academic_manager',
key: 'id'
}
} */
});
Campus.associate = models => {
// Campus.hasOne(models.Manager, { foreignKey: 'id'});
// foreignKey `id` is wrong. Your models already by default have `id`, which is their own.
// you either define the name as `campus_id`, or just let sequelize handle it for you by not defining it at all and just use `Campus.hasOne(models.Manager)`.
// but generally it's good practice to define, otherwise when you need it, you have to figure out what did sequelize help you name it as.
// read: https://sequelize.org/master/manual/assocs.html#providing-the-foreign-key-name-directly
Campus.hasOne(models.Manager, { foreignKey: 'campus_id'); // this means please inject `campus_id` into `Manager`
}
return Campus;
};
export default Campus;
Run Code Online (Sandbox Code Playgroud)
const Manager = (sequelize, DataTypes) =>{
const Manager = sequelize.define('Manager', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false
}
});
Manager.associate = models => {
// you don't define foreignKey here. because by doing so you are saying
// you want to inject this foreignKey into `Campus`, which you are not.
Manager.belongsTo(models.Campus);
}
return Manager;
};
export default Manager;
Run Code Online (Sandbox Code Playgroud)
在关系数据库中,经验法则是在任何 2 个模型之间,只能有 1 条路径,否则会形成循环依赖,这可能会导致问题。
LocationCampus.hasOne(Manager)
Manager.belongsTo(Campus)
Location.hasOne(Campus)
Location.belongsTo(Campus)
Run Code Online (Sandbox Code Playgroud)
一切都很好。让我们想象一下,假设Manager停留在 上,你可以这样Campus找到它们Location
Manager -> Campus -> Location
Run Code Online (Sandbox Code Playgroud)
直到您确定这是一个真实的陈述,Manager将始终留在该陈述中Location而不是其他地方,并且您的应用程序更频繁地需要此信息时,您将很想这样做:
Location.hasOne(Manager)
Manager.belongsTo(Location)
Run Code Online (Sandbox Code Playgroud)
现在您有了另一条路径Location -> Manager,并且完成了循环引用Location -> Manager -> Campus -> Location -> Manager....
要打破这一点,您必须在哪种关系更重要或更常访问之间做出选择。在这种情况下,看起来Location和之间的关系Manager似乎并不那么重要,那么就继续使用Manager -> Campus -> Location。
在这里,您无需关联模型,只需使用引用键或使用constraints: false. 阅读https://sequelize.org/master/manual/constraints-and-circularities.html
constraints: false是我通常的选择,因为它仍然为我提供了所有的续集方法,就好像模型是关联的一样。reference keys但严格来说,最多使用是正确的。然后执行手动联接,或使用您找到的引用键执行 2 次查询,以在其引用表上找到其数据。
我的解决方案是我没有在模型索引中建立关联。我错过了这个:
Object.keys(models).forEach(key => {
if ('associate' in models[key]) {
models[key].associate(models);
}
});
Run Code Online (Sandbox Code Playgroud)
永远记住要真正进行联想。
| 归档时间: |
|
| 查看次数: |
3557 次 |
| 最近记录: |