如何用Sequelize CLI配置Post/Video与Comment的多态关联?
使用Sequelize CLI的ES6格式实现多态关联
一、修改Comment的迁移文件
首先需要在Comment表中添加多态关联所需的两个核心字段:commentableId(存储关联目标的ID)和commentableType(存储关联目标的模型类型,比如Post或Video)。
打开migrations/[timestamp]-create-comment.js,修改up方法的字段定义:
'use strict'; /** @type {import('sequelize-cli').Migration} */ export default { async up(queryInterface, Sequelize) { await queryInterface.createTable('Comments', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, // 保留你原本定义的Comment字段,比如评论内容 content: { type: Sequelize.TEXT, allowNull: false }, // 添加多态关联字段 commentableId: { type: Sequelize.INTEGER, allowNull: false }, commentableType: { type: Sequelize.STRING, allowNull: false }, createdAt: { allowNull: false, type: Sequelize.DATE }, updatedAt: { allowNull: false, type: Sequelize.DATE } }); }, async down(queryInterface, Sequelize) { await queryInterface.dropTable('Comments'); } };
二、修改模型文件
1. Post模型(models/post.js)
在associate方法中定义hasMany关联,指定关联到Comment,并通过scope限定关联的commentableType为Post:
'use strict'; import { Model } from 'sequelize'; export default class Post extends Model { static init(sequelize, DataTypes) { return super.init({ // 保留你原本定义的Post字段,比如标题、内容 title: { type: DataTypes.STRING, allowNull: false }, content: { type: DataTypes.TEXT, allowNull: false } }, { sequelize, modelName: 'Post', }); } static associate(models) { // Post拥有多个Comment,关联字段为commentableId this.hasMany(models.Comment, { as: 'comments', foreignKey: 'commentableId', constraints: false, // 多态关联通常关闭外键约束,避免数据库层面的限制 scope: { commentableType: 'Post' } }); } }
2. Video模型(models/video.js)
逻辑和Post模型一致,仅需将scope中的commentableType设为Video:
'use strict'; import { Model } from 'sequelize'; export default class Video extends Model { static init(sequelize, DataTypes) { return super.init({ // 保留你原本定义的Video字段,比如标题、视频地址 title: { type: DataTypes.STRING, allowNull: false }, url: { type: DataTypes.STRING, allowNull: false } }, { sequelize, modelName: 'Video', }); } static associate(models) { // Video拥有多个Comment,关联字段为commentableId this.hasMany(models.Comment, { as: 'comments', foreignKey: 'commentableId', constraints: false, scope: { commentableType: 'Video' } }); } }
3. Comment模型(models/comment.js)
定义belongsTo关联,分别关联到Post和Video,使用相同的别名commentable,让Sequelize自动识别关联目标:
'use strict'; import { Model } from 'sequelize'; export default class Comment extends Model { static init(sequelize, DataTypes) { return super.init({ // 保留你原本定义的Comment字段 content: { type: DataTypes.TEXT, allowNull: false }, // 多态关联字段,需和迁移文件定义一致 commentableId: { type: DataTypes.INTEGER, allowNull: false }, commentableType: { type: DataTypes.STRING, allowNull: false } }, { sequelize, modelName: 'Comment', }); } static associate(models) { // Comment属于Post,别名为commentable this.belongsTo(models.Post, { as: 'commentable', foreignKey: 'commentableId', constraints: false, targetKey: 'id' }); // Comment属于Video,别名为commentable this.belongsTo(models.Video, { as: 'commentable', foreignKey: 'commentableId', constraints: false, targetKey: 'id' }); } }
三、同步数据库并验证关联
完成文件修改后,运行迁移命令同步数据库结构:
npx sequelize-cli db:migrate
之后就可以使用关联功能:
- 创建Post的评论:
const post = await Post.findByPk(1); await post.createComment({ content: '这是帖子的评论' }); - 创建Video的评论:
const video = await Video.findByPk(1); await video.createComment({ content: '这是视频的评论' }); - 查询评论所属的目标:
const comment = await Comment.findByPk(1, { include: 'commentable' }); console.log(comment.commentable); // 返回对应的Post或Video实例
内容的提问来源于stack exchange,提问作者JAYANTA SINGH
相关产品推荐
相关产品推荐

