Reputation: 457
For an existing MySQL database, I used Sequelize-auto package to generate the models. But the associations don't come with model classes.
I have an MySQL database and I'm using it for NodeJS web project. Also I'm using Sequelize as the ORM. Since database is already there I wanted to generate the model classes as the entities. So I used sequelize-auto
https://github.com/sequelize/sequelize-auto to generate the model classes. But when they were generated attributes have been correctly set but the associations doesn't come up with the model classes. So I have faced problem when fetching the data from the database.
Here are the two model classes that were generated with sequlize-auto. There are two table in the database named as department and category. department.js and category.js are the two model classes that were generated
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,
});
};
So what else needs to be done in order to get the associations and to fetch data successfully. Can some one help me here. Table structure is as following.
Upvotes: 5
Views: 2525
Reputation: 1
I followed the pattern demonstrated in the typescript example on sequelize-auto (init-models.ts) - within the existing initModels function, works fine in js.
export function initModels(sequelize: Sequelize) {
Product.initModel(sequelize);
Supplier.initModel(sequelize);
Supplier.hasMany(Product, { as: "products", foreignKey: "supplierId"});
return {...
Upvotes: 0
Reputation: 3436
To add to @CodingLittles answer which he based from here.
I added the following for making many to many assosiations:
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 });
}
}
});
})
Note that for the many to many relations to work you have to add the relations manually like I did in the getJunction
function
Upvotes: 1
Reputation: 1857
1) inside of your models folder create an index.js file and add the following code
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) inside of your resolver just reference the above:
const db = require('../assets/models/index');
Upvotes: 2