我创建了一种我认为非常棒的技术,甚至允许跨外键使用复合唯一键。
我将举一个带有基本 user.js 模型类文件的示例
models/user.js
const { Model, DataTypes } = require('sequelize');
module.exports = function(sequelize){
class User extends Model {}
return User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
trading_system_key: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
modelName: 'User',
indexes: [{ unique: true, fields: ['trading_system_key'] }]
});
};
这显示了一个简单的用户类示例,还没有关联,但下一个文件将使用它。
models/algorithm.js
const { Model, DataTypes } = require('sequelize');
const User = require('../models/user');
module.exports = function(sequelize){
class Algorithm extends Model {}
UserModel = User(sequelize);//@JA - Gets a defined version of user class
var AlgorithmFrame = Algorithm.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
user_Id: {
type: DataTypes.INTEGER,
references: {
model: UserModel,
key: 'id',
},
}
}, {
sequelize,
modelName: 'Algorithm',
indexes: [{ unique: true, fields: ['name','user_id'] }]
});
return AlgorithmFrame
};
这个例子展示了如何创建一个外键引用,而不必说belongsTo或HasOne等...当你需要创建复合键时,这会派上用场。
例如,注意我把indexes: [{ unique: true, fields: ['name','user_id'] }]
这使得 name 和 user_id 不能相同(复合键)。因此,例如,如果名称是 Joe 并且 user_id 是 1,并且我尝试创建另一个具有相同详细信息的记录,它会拒绝它,但如果我创建名称为 Rachel 和 user_id 1 的东西,它会允许它,因为它只是唯一的如果两者相同。
据我所知,除非您以这种方式设置,否则无法使用复合键。
此技术的另一个优点是模型位于单独的文件中并定义为类!
那么我该如何使用这些呢?
(在您的文件中定义续集连接...)
api.js
const { Sequelize, DataTypes, Model } = require('sequelize');
const User = require('../models/user');
const Algorithm = require('../models/algorithm');
const sequelize = new Sequelize('database', 'username', 'passwordhere', {
host: 'db',
dialect: 'mysql' /* one of 'mysql' | 'mariadb' | 'postgres' | 'mssql' */
});
const UserModel = User(sequelize);
const AlogorithmModel = Algorithm(sequelize);
(async () => {
try {
await sequelize.authenticate();
await UserModel.sync({ alter: true });
await AlogorithmModel.sync({ alter: true });
//Do something with the models now....
//Etc...
} catch (error) {
console.error('Unable to connect to the database:', error);
}
});
这种技术之所以有效,是因为类文件是如何定义的。在典型的软件开发中,您包含类并引用它并实例化它,但在这种情况下我们已经在传递它的实例化版本
例如,您会注意到在类文件中我定义了class user extends model {},它里面只是空的。然后我们返回该类的实例化版本。当您以这种方式使用 module.exports 时,它实际上需要一个 sequelize 连接实例的参数。
这就是为什么在 api.js 文件中我说 const User = require('../models/user');,这会引用文件返回的“函数”。
除非你将它传递给 sequelize,否则该函数不会做任何事情,所以你看到的下一行...
const UserModel = User(sequelize);
通过这样做,您可以将模型放在单独的文件中,并将它们作为类,它们仍然可以具有关联甚至复合索引!
希望对你有所帮助。
更新::
如果您想要 onUpdate 或 onDelete 级联选项,只需像这样使用模型定义它。
algorithm_id: {
type: DataTypes.INTEGER,
allowNull: false,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
references: {
model: AlgorithmModel,
key: 'id',
}
},
您也可以设置是否希望它为空,但是,请记住 allowNull 将无法与“alter”表命令一起使用,除非首先删除了外键! onUpdate 和 onDelete 似乎可以与 alter 一起使用。