如何在Sequelize Postgres中构建Category与Sub-category的一对多关系
在Sequelize中构建Category与SubCategory的一对多关系
要实现一个Category拥有多个SubCategory、一个SubCategory属于一个Category的一对多关系,需要完成两个核心步骤:给SubCategory添加外键字段,以及在两个模型间建立关联绑定。以下是具体的代码修改和实现方案:
1. 修改SubCategory模型,添加外键字段
在SubCategory的模型定义中,新增category_id字段作为关联Category的外键,类型与Category的主键(UUID)保持一致:
const { DataTypes } = require("sequelize"); const { getConnection } = require("../helper/databaseConnection"); const subcatModel = { subcat_id: { primaryKey: true, type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, }, subcat_name: { type: DataTypes.STRING, allowNull: false, }, // 新增外键字段,关联Category的category_id category_id: { type: DataTypes.UUID, allowNull: false, references: { model: 'category', // 对应Category模型的表名(因freezeTableName: true,表名即为category) key: 'category_id' }, onDelete: 'CASCADE', // 可选:删除分类时自动删除其子分类,也可设为RESTRICT禁止删除有子分类的分类 onUpdate: 'CASCADE' } }; let subcat = null; const initSubcatModel = async () => { try { if (subcat) return subcat; const sequelize = await getConnection(); subcat = sequelize.define("sub_category", subcatModel, { freezeTableName: true, }); await subcat.sync({ alter: true }); return subcat; } catch (err) { console.log("sub category", err); } }; module.exports = { initSubcatModel };
2. 统一初始化模型并建立关联
由于两个模型都是异步初始化的,需要确保两者都初始化完成后再调用关联方法。建议创建一个统一的初始化文件(比如models/index.js)来处理:
const { initCategoryModel } = require('./category'); const { initSubcatModel } = require('./sub-category'); async function initModels() { const Category = await initCategoryModel(); const SubCategory = await initSubcatModel(); // 建立一对多关联 Category.hasMany(SubCategory, { foreignKey: 'category_id', // 对应SubCategory中的外键字段 as: 'subcategories' // 查询时的别名,用于包含子分类数据 }); SubCategory.belongsTo(Category, { foreignKey: 'category_id', as: 'category' // 查询时的别名,用于包含父分类数据 }); return { Category, SubCategory }; } module.exports = { initModels };
3. 关联后的使用示例
完成关联后,就可以通过include选项查询关联数据:
const { initModels } = require('./models'); // 查询指定分类及其所有子分类 async function getCategoryWithSubcats(categoryId) { const { Category } = await initModels(); const category = await Category.findByPk(categoryId, { include: ['subcategories'] // 使用关联时定义的别名 }); return category; } // 查询指定子分类及其所属分类 async function getSubcatWithCategory(subcatId) { const { SubCategory } = await initModels(); const subcat = await SubCategory.findByPk(subcatId, { include: ['category'] }); return subcat; }
注意事项
references.model必须与Category模型的表名一致(因设置了freezeTableName: true,表名就是category)onDelete和onUpdate可根据业务需求调整:若不希望删除分类时删除子分类,可设为RESTRICT;若允许子分类不属于任何分类,可将allowNull设为true并将onDelete设为SET NULL- 必须在两个模型都初始化完成后再调用关联方法,否则会出现模型未定义的错误
内容的提问来源于stack exchange,提问作者sumanth.js
相关产品推荐
相关产品推荐

