Sequelize:嵌套包含/反向关联的问题
Sequelize: Problems with nested include / reverse association
我是 JS 和 Sequelize 的新手,现在在查询以下结构时遇到问题。也许我在这里完全遗漏了一些基本点。非常感谢您的帮助。
版本:
- 节点:15.13.0
- 续集:6.6.2
- postgres: 13.3
- pg: 8.6.0
- pg-hstore: 2.3.3
结构
一个航班始终属于一个用户。不同的用户可以对一个航班创建评论。
目标
当我 select 一个航班的 ID 时,我想包含用户的姓名,并且我想包含对该航班的所有评论以及创建评论的用户的姓名。
问题
我可以将评论包含在航班中。但我无法实现其他目标。
当我运行:
await Flight.findOne({
where: { id: flightId },
include: [
{
model: User,
as: "user",
attributes: ["id", "name"],
},
{
model: FlightComment,
as: "comments",
},
],
});
我会得到错误
SequelizeEagerLoadingError: User is not associated to Flight!
这是可以理解的。所以我尝试将反向关联添加到Flight。
Flight.belongsTo(User)
之后我会得到错误
Flight.belongsTo called with something that's not a subclass of Sequelize.Model
当我在 FlightComment 中定义一个 userId 列时:
userId: {
type: DataTypes.UUID,
references: {
model: User,
key: "id",
},
},
我在数据库同步过程中会出现以下错误
Executing (default): DROP TABLE IF EXISTS "FlightComments" CASCADE;
TypeError: Cannot read property 'replace' of undefined
我读到您需要在一个文件中定义所有模型,但由于有许多不同的模型,我想将它们分开。
我也没有在官方文档中找到任何建议。
模型文件
我为每个模型创建了一个自己的文件(会有很多不同的模型,所以最好把它们分开)。
飞行文件:
const Flight = db.sequelize.define("Flight", {
//Many beautiful attributes
});
Flight.hasMany(FlightComment, {
as: "comments",
foreignKey: {
name: "flightId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true,
});
//Another association
module.exports = Flight;
FlightComment 文件:
const FlightComment = db.sequelize.define("FlightComment", {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
message: {
type: DataTypes.STRING,
allowNull: false,
},
});
module.exports = FlightComment;
用户文件:
const User = db.sequelize.define(
"User",
{
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
//Many more attributes
},
);
User.hasMany(Flight, {
as: "flights",
foreignKey: {
name: "userId",
allowNull: false,
},
});
User.hasMany(FlightComment, {
as: "comments",
foreignKey: {
name: "userId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true,
});
module.exports = User;
最后,我在一个文件中定义了所有依赖于另一个模型的模型。
这不是我正在寻找的解决方案,但它有效...
您可以通过编程方式初始化数据库及其关联(使用与模型位于同一文件夹中的文件),例如:
'use strict'
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const config = {
"username": "root",
"password": "YOUR ROOT PASSWORD HERE",
"database": "YOUR DATABASE NAME HERE",
"dialect": "postgres"
}
const db = {}
let sequelize = new Sequelize(config.database, config.username, config.password, config);
fs.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0)
&& (file !== basename)
&& (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
有了这个,你需要像这样声明你的模型文件:
module.exports = Flight = (sequelize, DataTypes) => {
const Flight = sequelize.define('Flight', {
//Many beautiful attributes
})
Flight.associate = models => {
Flight.hasMany(models.FlightComment, {
as: 'comments',
foreignKey: {
name: "flightId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true
})
Flight.belongsTo(models.User, {
as: 'flight',
foreignKey: {
name: "flightId",
allowNull: false,
}
})
}
return Flight
}
我是 JS 和 Sequelize 的新手,现在在查询以下结构时遇到问题。也许我在这里完全遗漏了一些基本点。非常感谢您的帮助。
版本:
- 节点:15.13.0
- 续集:6.6.2
- postgres: 13.3
- pg: 8.6.0
- pg-hstore: 2.3.3
结构
一个航班始终属于一个用户。不同的用户可以对一个航班创建评论。目标
当我 select 一个航班的 ID 时,我想包含用户的姓名,并且我想包含对该航班的所有评论以及创建评论的用户的姓名。问题
我可以将评论包含在航班中。但我无法实现其他目标。 当我运行:await Flight.findOne({
where: { id: flightId },
include: [
{
model: User,
as: "user",
attributes: ["id", "name"],
},
{
model: FlightComment,
as: "comments",
},
],
});
我会得到错误
SequelizeEagerLoadingError: User is not associated to Flight!
这是可以理解的。所以我尝试将反向关联添加到Flight。
Flight.belongsTo(User)
之后我会得到错误
Flight.belongsTo called with something that's not a subclass of Sequelize.Model
当我在 FlightComment 中定义一个 userId 列时:
userId: {
type: DataTypes.UUID,
references: {
model: User,
key: "id",
},
},
我在数据库同步过程中会出现以下错误
Executing (default): DROP TABLE IF EXISTS "FlightComments" CASCADE;
TypeError: Cannot read property 'replace' of undefined
我读到您需要在一个文件中定义所有模型,但由于有许多不同的模型,我想将它们分开。
我也没有在官方文档中找到任何建议。
模型文件
我为每个模型创建了一个自己的文件(会有很多不同的模型,所以最好把它们分开)。
飞行文件:
const Flight = db.sequelize.define("Flight", {
//Many beautiful attributes
});
Flight.hasMany(FlightComment, {
as: "comments",
foreignKey: {
name: "flightId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true,
});
//Another association
module.exports = Flight;
FlightComment 文件:
const FlightComment = db.sequelize.define("FlightComment", {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
message: {
type: DataTypes.STRING,
allowNull: false,
},
});
module.exports = FlightComment;
用户文件:
const User = db.sequelize.define(
"User",
{
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
//Many more attributes
},
);
User.hasMany(Flight, {
as: "flights",
foreignKey: {
name: "userId",
allowNull: false,
},
});
User.hasMany(FlightComment, {
as: "comments",
foreignKey: {
name: "userId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true,
});
module.exports = User;
最后,我在一个文件中定义了所有依赖于另一个模型的模型。 这不是我正在寻找的解决方案,但它有效...
您可以通过编程方式初始化数据库及其关联(使用与模型位于同一文件夹中的文件),例如:
'use strict'
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const config = {
"username": "root",
"password": "YOUR ROOT PASSWORD HERE",
"database": "YOUR DATABASE NAME HERE",
"dialect": "postgres"
}
const db = {}
let sequelize = new Sequelize(config.database, config.username, config.password, config);
fs.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0)
&& (file !== basename)
&& (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
有了这个,你需要像这样声明你的模型文件:
module.exports = Flight = (sequelize, DataTypes) => {
const Flight = sequelize.define('Flight', {
//Many beautiful attributes
})
Flight.associate = models => {
Flight.hasMany(models.FlightComment, {
as: 'comments',
foreignKey: {
name: "flightId",
allowNull: false,
},
onDelete: "CASCADE",
hooks: true
})
Flight.belongsTo(models.User, {
as: 'flight',
foreignKey: {
name: "flightId",
allowNull: false,
}
})
}
return Flight
}