在多个文件中 Sequelize 一对多关联
Sequelize one to many assocation in multiple files
我正在处理与 sequelize 的一对多关联。大多数教程和文档都会显示在同一文件中定义两个模型时的示例。
我目前有两个文件,第一个 city.js:
const Promise = require('bluebird');
var Country = require('./country');
var City = sequelize.define("City", {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},...
}, {
freezeTableName: true,
timestamps: false
});
City.belongsTo(Country, {foreignKey : 'countryId', as: 'Country'});
Promise.promisifyAll(City);
module.exports = City;
还有第二个文件country.js:
const Promise = require('bluebird');
var City = require('./city');
var Country = sequelize.define("Country", {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},
...
}, {
freezeTableName: true,
timestamps: false,
paranoid: false
});
Country.hasMany(City, {foreignKey : 'countryId', as: 'Cities'});
Promise.promisifyAll(Country);
module.exports = Country;
当我导入两个模块并尝试实例化对象时:
var City = require('../model/external/city');
var CountryRepository = require('../repository/external/countryRepository');
CountryRepository.findById(1).then(function(country) {
var city = City.build();
city.name = 'Paris';
city.setCountry(country);
console.log('OK');
});
我收到以下错误:
throw new Error(this.name + '.' +
Utils.lowercaseFirst(Type.toString()) + ' called with something
that\'s not an instance of Sequelize.Model')
问题是模型在从模型导出之前就已经被 promified 了还是我遗漏了什么?
我不确定您的代码到底有什么问题,需要 运行 才能确定。
但是当您正在寻找示例时,请查看 Sequelize Github 中的示例。
它在不同的文件中声明模型并在 index.js
中关联它们。
稍后您可以使用简单的 model
属性引用您的其他模型 model.Country
:
City.belongsTo(model.Country, {foreignKey : 'countryId', as: 'Country'});
例如,user.js.
您必须在导出所有模型后声明关联
我遇到了同样的问题!
我创造了一种我认为非常好的技术,甚至允许跨外键使用复合唯一键。
我将举一个基本的例子 user.js 模型 class 文件
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'] }]
});
};
这显示了用户 class 的一个简单示例,尚未关联,但下一个文件将使用它。
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'] }]
这使得名称和 user_id 不能相同(复合键)。因此,例如,如果名字是 Joe 而 user_id 是 1 并且我试图创建另一个具有相同详细信息的记录它会拒绝它,但是如果我创建了名称为 Rachel 并且 user_id 1 的东西会允许它,因为它只有在两者相同时才是唯一的。
据我所知,除非您以这种方式设置,否则无法使用复合键。
此技术的另一个优点是模型位于单独的文件中并定义为 classes!
那么我该如何使用这些呢?
(在你的文件中你定义了sequelize连接...)
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 文件的定义方式,此技术有效。在典型的软件开发中,您包含 class 并引用它并实例化它,但在这种情况下 我们已经传递了它的实例化版本
例如,您会在 class 文件中注意到我定义了 class user extends model {}
并且它里面只是空的。然后我们 return class 的实例化版本。当您以这种方式使用 module.exports 时,它实际上需要一个 sequelize 连接实例的参数。
这就是为什么在 api.js 文件中我说 const User = require('../models/user');
,这引用了文件 returning 中的 'function'。
该函数不会执行任何操作,除非您将其传递给 sequelize,因此您会看到下一行...
const UserModel = User(sequelize);
通过这样做,您可以将模型放在单独的文件中并使它们成为 classes,并且它们仍然可以具有关联甚至复合索引!
希望这对您有所帮助。
更新::
如果你想要 onUpdate 或 onDelete 级联选项,只需像这样用模型定义它。
algorithm_id: {
type: DataTypes.INTEGER,
allowNull: false,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
references: {
model: AlgorithmModel,
key: 'id',
}
},
您也可以设置是否希望它为 null,但是请记住,allowNull 将无法与 'alter' table 命令一起使用,除非首先删除了外键!不过,onUpdate 和 onDelete 似乎与 alter 一起工作得很好。
我正在处理与 sequelize 的一对多关联。大多数教程和文档都会显示在同一文件中定义两个模型时的示例。 我目前有两个文件,第一个 city.js:
const Promise = require('bluebird');
var Country = require('./country');
var City = sequelize.define("City", {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},...
}, {
freezeTableName: true,
timestamps: false
});
City.belongsTo(Country, {foreignKey : 'countryId', as: 'Country'});
Promise.promisifyAll(City);
module.exports = City;
还有第二个文件country.js:
const Promise = require('bluebird');
var City = require('./city');
var Country = sequelize.define("Country", {
id: {
type: DataTypes.INTEGER,
field: 'id',
primaryKey: true,
autoIncrement: true
},
...
}, {
freezeTableName: true,
timestamps: false,
paranoid: false
});
Country.hasMany(City, {foreignKey : 'countryId', as: 'Cities'});
Promise.promisifyAll(Country);
module.exports = Country;
当我导入两个模块并尝试实例化对象时:
var City = require('../model/external/city');
var CountryRepository = require('../repository/external/countryRepository');
CountryRepository.findById(1).then(function(country) {
var city = City.build();
city.name = 'Paris';
city.setCountry(country);
console.log('OK');
});
我收到以下错误:
throw new Error(this.name + '.' + Utils.lowercaseFirst(Type.toString()) + ' called with something that\'s not an instance of Sequelize.Model')
问题是模型在从模型导出之前就已经被 promified 了还是我遗漏了什么?
我不确定您的代码到底有什么问题,需要 运行 才能确定。
但是当您正在寻找示例时,请查看 Sequelize Github 中的示例。
它在不同的文件中声明模型并在 index.js
中关联它们。
稍后您可以使用简单的 model
属性引用您的其他模型 model.Country
:
City.belongsTo(model.Country, {foreignKey : 'countryId', as: 'Country'});
例如,user.js.
您必须在导出所有模型后声明关联
我遇到了同样的问题!
我创造了一种我认为非常好的技术,甚至允许跨外键使用复合唯一键。
我将举一个基本的例子 user.js 模型 class 文件
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'] }]
});
};
这显示了用户 class 的一个简单示例,尚未关联,但下一个文件将使用它。
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'] }]
这使得名称和 user_id 不能相同(复合键)。因此,例如,如果名字是 Joe 而 user_id 是 1 并且我试图创建另一个具有相同详细信息的记录它会拒绝它,但是如果我创建了名称为 Rachel 并且 user_id 1 的东西会允许它,因为它只有在两者相同时才是唯一的。
据我所知,除非您以这种方式设置,否则无法使用复合键。
此技术的另一个优点是模型位于单独的文件中并定义为 classes!
那么我该如何使用这些呢?
(在你的文件中你定义了sequelize连接...) 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 文件的定义方式,此技术有效。在典型的软件开发中,您包含 class 并引用它并实例化它,但在这种情况下 我们已经传递了它的实例化版本
例如,您会在 class 文件中注意到我定义了 class user extends model {}
并且它里面只是空的。然后我们 return class 的实例化版本。当您以这种方式使用 module.exports 时,它实际上需要一个 sequelize 连接实例的参数。
这就是为什么在 api.js 文件中我说 const User = require('../models/user');
,这引用了文件 returning 中的 'function'。
该函数不会执行任何操作,除非您将其传递给 sequelize,因此您会看到下一行...
const UserModel = User(sequelize);
通过这样做,您可以将模型放在单独的文件中并使它们成为 classes,并且它们仍然可以具有关联甚至复合索引!
希望这对您有所帮助。
更新::
如果你想要 onUpdate 或 onDelete 级联选项,只需像这样用模型定义它。
algorithm_id: {
type: DataTypes.INTEGER,
allowNull: false,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
references: {
model: AlgorithmModel,
key: 'id',
}
},
您也可以设置是否希望它为 null,但是请记住,allowNull 将无法与 'alter' table 命令一起使用,除非首先删除了外键!不过,onUpdate 和 onDelete 似乎与 alter 一起工作得很好。