序列化:对包含联接的表使用include

时间:2019-02-11 03:42:55

标签: mysql join many-to-many sequelize.js

我有4个模型:UserSkillSkillToLearnSkillToTeachSkillToLearnSkillToTeach包含两列userIdskillId,用于跟踪用户(由userId赋予)想要学习或教导的技能(由skillId赋予)

我的目标是使用Sequelize的include语句,以便我可以返回所有用户的数据,包括他们正在学习的技能列表和他们正在教技能的列表。我想要类似以下内容的响应:

[
    {
        "id": 1,
        "username": "janedoe",
        "skillsLearning": [
            {
                "skillId": 1,
                "name": "arts"
            }
        ],
        "skillsTeaching": [
            {
                "skillId": 2,
                "name": "cooking"
            }
        ]
    }
]

但是,相反,我得到以下响应:

[
    {
        "id": 1,
        "username": "janedoe",
        "skillsLearning": [
            {
                "skillId": 1,
                "Skill": {
                    "name": "arts"
                }
            }
        ],
        "skillsTeaching": [
            {
                "skillId": 2,
                "Skill": {
                    "name": "cooking"
                }
            }
        ]
    }
]

我尝试包括Skill而不是SkillToLearnSkillToTeach,但是我收到一个错误消息,说SkillUser没有关联。我不确定我的模式和关联是否正确。

User.js

    const User = sequelize.define("User", {
        username: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true
        },
        email: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true,
            validate: {
                isEmail: true
            }
        },
        password: {
            type: DataTypes.STRING,
            allowNull: false
        },
        description: {
            type: DataTypes.TEXT
        }
    }, {
        freezeTableName: true
    });

    User.associate = function (models) {
        User.hasMany(models.SkillToLearn, {
            as: "skillsLearning",
            onDelete: "cascade",
            foreignKey: "userId",
            sourceKey: "id"
        });

        User.hasMany(models.SkillToTeach, {
            as: "skillsTeaching",
            onDelete: "cascade",
            foreignKey: "userId",
            sourceKey: "id"
        });
    };

Skill.js

const Skill = sequelize.define("Skill", {
        name: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true
        }
    }, {
        freezeTableName: true
    });

    Skill.associate = function (models) {
        Skill.hasMany(models.SkillToLearn, {
            as: "usersLearning",
            onDelete: "cascade",
            foreignKey: "skillId",
            sourceKey: "id"
        });

        Skill.hasMany(models.SkillToTeach, {
            as: "usersTeaching",
            onDelete: "cascade",
            foreignKey: "skillId",
            sourceKey: "id"
        });
    };

SkillToLearn.js

const SkillToLearn = sequelize.define("SkillToLearn", {
        userId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true
        },
        skillId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true
        }
    }, {
        freezeTableName: true
    });

    SkillToLearn.associate = function (models) {
        SkillToLearn.belongsTo(models.User, {
            foreignKey: "userId",
            targetKey: "id"
        });

        SkillToLearn.belongsTo(models.Skill, {
            foreignKey: "skillId",
            targetKey: "id"
        });
    };

SkillToTeach.js

const SkillToTeach = sequelize.define("SkillToTeach", {
        userId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true
        },
        skillId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true
        }
    }, {
        freezeTableName: true
    });

    SkillToTeach.associate = function (models) {
        SkillToTeach.belongsTo(models.User, {
            foreignKey: "userId",
            targetKey: "id"
        });

        SkillToTeach.belongsTo(models.Skill, {
            foreignKey: "skillId",
            targetKey: "id"
        });
    };

dataRoutes.js

db.User
        .findAll({
            attributes: ["id", "username"],
            include: [
                {
                    model: db.SkillToLearn,
                    as: "skillsLearning",
                    attributes: ["skillId"],
                    include: [
                        {
                            model: db.Skill,
                            attributes: ["name"]
                        }
                    ]
                },
                {
                    model: db.SkillToTeach,
                    as: "skillsTeaching",
                    attributes: ["skillId"],
                    include: [
                        {
                            model: db.Skill,
                            attributes: ["name"]
                        }
                    ]
                }
            ]
        })
        .then(results => res.json(results));
});

我是否有办法在没有对象的情况下获得该技能的名称?我是否应该使用自己的对象文字进行多个查询并构造响应?谢谢!

0 个答案:

没有答案