Sequelize Eager Loading标签映射关联

huangapple go评论119阅读模式
英文:

Sequelize Eager Loading tag map association

问题

以下是你要翻译的内容:

I am trying to implement a three table solution for project/post tags.

These are my models:

projects.model.js

const Projects = db.sequelize.define(
    'Projects',
    {
        project_id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true,
            allowNull: false,
        },

        creator_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: User,
                key: 'id'
            }
        },

        project_title: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        },

        project_description: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        },

        creation_date: {
            type: Sequelize.DataTypes.DATE,
            allowNull: false,
            defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
        },

        last_updated_date: {
            type: Sequelize.DataTypes.DATE,
            allowNull: false,
            defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
        }
    }, {
    timestamps: false
    }
)

export default Projects

project-tags.model.js

const ProjectTags = db.sequelize.define(
    'Project Tags',
    {
        id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },

        project_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: Projects,
                key: 'project_id'
            }
        },

        project_tag_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: Tags,
                key: 'id'
            }
        },

    }, {
    timestamps: false
});
Tags.belongsToMany(Projects, { through: ProjectTags, foreignKey: 'project_id', as: 'tags' });
Projects.belongsToMany(Tags, { through: ProjectTags, foreignKey: 'project_tag_id', as: 'tags' });

export default ProjectTags

tags.model.js

const Tags = db.sequelize.define(
    'Tags',
    {
        id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },

        tag: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        }
    }, {
    timestamps: false
});

export default Tags

And I am eager loading it like that:

const projects = Projects.findAll({
            attributes: ['project_id','creator_id','project_title','project_description','creation_date','last_updated_date'],
            include: [{
                model: Tags,
                as: 'tags',
                attributes: ['tag'],
            }]
        })
        .catch(error => {
            throw an Error(error);
        })
        return projects;

It returns the project data fine, but tags is an empty array although the table is not empty and the references seem to be correct. What am I missing here?

英文:

I am trying to implement a three table solution for project/post tags.

Sequelize Eager Loading标签映射关联

These are my models:

projects.model.js

const Projects = db.sequelize.define (
    'Projects',
    {
        project_id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true,
            allowNull: false,
        },
        
        creator_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: User,
                key: 'id'
            }
        },

        project_title: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        },

        project_description: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        },

        creation_date: {
            type: Sequelize.DataTypes.DATE,
            allowNull: false,
            defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
        },

        last_updated_date: {
            type: Sequelize.DataTypes.DATE,
            allowNull: false,
            defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
        }
    }, {
    timestamps: false
    }
)

export default Projects

project-tags.model.js

const ProjectTags = db.sequelize.define(
    'Project Tags',
    {
        id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },

        project_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: Projects,
                key: 'project_id'
            }
        },

        project_tag_id: {
            type: Sequelize.DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: Tags,
                key: 'id'
            }
        },

    }, {
    timestamps: false
});
Tags.belongsToMany(Projects, { through: ProjectTags, foreignKey: 'project_id', as: 'tags' });
Projects.belongsToMany(Tags, { through: ProjectTags, foreignKey: 'project_tag_id', as: 'tags' });

export default ProjectTags

tags.model.js

const Tags = db.sequelize.define(
    'Tags',
    {
        id: {
            type: Sequelize.DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },

        tag: {
            type: Sequelize.DataTypes.STRING,
            allowNull: false
        }
    }, {
    timestamps: false
});

export default Tags

And I am eager loading it like that:

const projects = Projects.findAll({
            attributes: ['project_id','creator_id','project_title','project_description','creation_date','last_updated_date'],
            include: [{
                model: Tags,
                as: 'tags',
                attributes: ['tag'],
            }]
        })
        .catch(error => {
            throw new Error(error);
        })
        return projects;

It returns the project data fine, but tags is an empty array although the table is not empty and the references seem to be correct. What am I missing here?

答案1

得分: 1

你在关联中混淆了外键选项。belongsToMany 上的 foreignKey 选项应指示连接到你调用 belongsToMany 的主模型的字段,而不是作为第一个参数传递的那个字段。当然,你还需要指定不同的别名(它们应与作为第一个参数传递的模型相对应):

Tags.belongsToMany(Projects, { through: ProjectTags, foreignKey: 'project_tag_id', otherKey: 'project_id', as: 'projects' });
Projects.belongsToMany(Tags, { through: ProjectTags, foreignKey: 'project_id', otherKey: 'project_tag_id', as: 'tags' });

如果你想指定传递的模型的键,你需要在 foreignKey 选项旁边使用 otherKey 选项。

英文:

You mixed up the foreign key options in associations. foreignKey option on belongsToMany should indicate the field that links the main model on which you call belongsToMany and not the one that you pass as the first argument. And of course you need to indicate different aliases (they should correspond to the passed model (as the first argument):

Tags.belongsToMany(Projects, { through: ProjectTags, foreignKey: 'project_tag_id', 
otherKey: 'project_id', as: 'projects' });
Projects.belongsToMany(Tags, { through: ProjectTags, foreignKey: 'project_id', otherKey: 'project_tag_id', as: 'tags' });

If you want to indicate the key for the passed model you need to use otherKey option next to foreignKey option.

huangapple
  • 本文由 发表于 2023年3月8日 16:39:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670880.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定