如何向 Sequelize-Auto 生成的模型添加关联
Posted
技术标签:
【中文标题】如何向 Sequelize-Auto 生成的模型添加关联【英文标题】:How to add associations to Models generated from Sequelize-Auto 【发布时间】:2019-08-18 04:47:22 【问题描述】:对于现有的 mysql 数据库,我使用 Sequelize-auto 包来生成模型。但是模型类没有关联。
我有一个 MySQL 数据库,我将它用于 NodeJS Web 项目。我也使用 Sequelize 作为 ORM。由于数据库已经存在,我想将模型类生成为实体。所以我用了sequelize-auto
https://github.com/sequelize/sequelize-auto 生成模型类。但是,当它们生成时,属性已正确设置,但关联并没有与模型类一起出现。所以我在从数据库中获取数据时遇到了问题。
这是使用 sequlize-auto 生成的两个模型类。数据库中有两个表,分别命名为部门和类别。 department.js 和 category.js 是生成的两个模型类
department.js
module.exports = function(sequelize, DataTypes)
return sequelize.define('department',
department_id:
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
,
name:
type: DataTypes.STRING(100),
allowNull: false
,
description:
type: DataTypes.STRING(1000),
allowNull: true
,
tableName: 'department',
timestamps: false,
);
;
category.js
module.exports = function(sequelize, DataTypes)
return sequelize.define('category',
category_id:
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
,
department_id:
type: DataTypes.INTEGER(11),
allowNull: false
,
name:
type: DataTypes.STRING(100),
allowNull: false
,
description:
type: DataTypes.STRING(1000),
allowNull: true
,
tableName: 'category',
timestamps: false,
);
;
那么还需要做什么才能获得关联并成功获取数据。有人可以在这里帮助我。表结构如下。
【问题讨论】:
sequelize auto 没有生成关联的功能,您必须手动执行。但是他们提供了一种使用生成的模型并将关联添加到它们的方法github.com/sequelize/sequelize-auto/issues/34 【参考方案1】:1) 在您的模型文件夹中创建一个 index.js 文件并添加以下代码
import Sequelize from 'sequelize';
const fs = require('fs');
const path = require('path');
const basename = path.basename(__filename);
const db = ;
// @ts-ignore
const sequelize = new Sequelize('dbname', 'dbUser', 'password',
host: '127.0.0.1',
port: 'PORT',
dialect: 'mysql',
define:
freezeTableName: true,
timestamps: false,
,
pool:
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
,
// <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
operatorsAliases: false,
);
const tableModel = ;
fs.readdirSync(__dirname)
.filter(file => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js')
.forEach(file =>
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
tableModel[model.name] = model;
);
Object.getOwnPropertyNames(db).forEach(modelName =>
const currentModel = db[modelName];
Object.getOwnPropertyNames(currentModel.rawAttributes).forEach(attributeName =>
if (
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName],
'references'
) &&
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName].references,
'model'
) &&
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName].references,
'key'
)
)
if (
!(
currentModel.rawAttributes[attributeName].references.model &&
currentModel.rawAttributes[attributeName].references.key
)
)
console.log(
`*SKIPPED* $modelName $attributeName references a model $currentModel.rawAttributes[attributeName].references.model with key $currentModel.rawAttributes[attributeName].references.key`
);
return;
console.log(
`$modelName $attributeName references a model $currentModel.rawAttributes[attributeName].references.model with key $currentModel.rawAttributes[attributeName].references.key`
);
const referencedTable =
tableModel[currentModel.rawAttributes[attributeName].references.model];
currentModel.belongsTo(referencedTable, foreignKey: attributeName );
referencedTable.hasMany(currentModel, foreignKey: attributeName );
);
);
// @ts-ignore
db.sequelize = sequelize;
// @ts-ignore
db.Sequelize = Sequelize;
// eslint-disable-next-line eol-last
module.exports = db;
2) 在您的解析器内部只需参考上述内容:
const db = require('../assets/models/index');
【讨论】:
【参考方案2】:添加到他基于here 的@CodingLittles 答案。
我添加了以下内容以进行多对多关联:
enum Junctions
user = 'user',
roles = 'roles',
enum JuntiontThrough
userroles = 'userroles',
interface JunctionObject
junctionBelongsTo?: any;
const checkIfAttrExists= (obj, value) =>
return Object.prototype.hasOwnProperty.call(obj, value);
;
const checkRefrence = (obj, attr, value) =>
return obj.rawAttributes[attr].references[value];
;
export const getJunction = (junc: Junctions): JunctionObject =>
const junctions =
user:
junctionBelongsTo: [
key: Junctions.roles, value: juntiontThrough.userroles
],
,
roles:
junctionBelongsTo: [ key: Junctions.user, value: juntiontThrough.userroles ],
,
[junc];
if (!junctions) return ;
return junctions;
;
const models = Object.getOwnPropertyNames(db);
models.forEach(modelName =>
const currentModel = db[modelName];
const junction = getJunction(modelName as Junctions);
if (!_.isEmpty(junction))
// eslint-disable-next-line array-callback-return
junction.junctionBelongsTo.reduce((key, value) =>
currentModel.belongsToMany(db[value.key],
through: db[value.value],
);
, );
const attributes = Object.getOwnPropertyNames(currentModel.rawAttributes);
attributes.forEach(attributeName =>
if (
checkIfAttrExists(currentModel.rawAttributes[attributeName], 'references') &&
checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'model') &&
checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'key')
)
if (
!(
checkRefrence(currentModel, attributeName, 'model') &&
checkRefrence(currentModel, attributeName, 'key')
)
)
return;
const referencedTable =
tableModel[currentModel.rawAttributes[attributeName].references.model];
if (!(modelName.toString() in juntiontThrough))
console.log(
`$modelName $attributeName references a model $currentModel.rawAttributes[attributeName].references.model with key $currentModel.rawAttributes[attributeName].references.key`
);
currentModel.belongsTo(referencedTable, foreignKey: attributeName );
referencedTable.hasMany(currentModel, foreignKey: attributeName );
);
)
请注意,要使多对多关系起作用,您必须像我在 getJunction
函数中所做的那样手动添加关系
【讨论】:
【参考方案3】:我遵循sequelize-auto (init-models.ts) 上的打字稿示例中演示的模式 - 在现有的 initModels 函数中,在 js 中可以正常工作。
export function initModels(sequelize: Sequelize)
Product.initModel(sequelize);
Supplier.initModel(sequelize);
Supplier.hasMany(Product, as: "products", foreignKey: "supplierId");
return ...
【讨论】:
以上是关于如何向 Sequelize-Auto 生成的模型添加关联的主要内容,如果未能解决你的问题,请参考以下文章
nodejs利用sequelize-auto 根据数据库的table 生成model