Ассоциация Sequelize 4 не работает, как предполагается - PullRequest
0 голосов
/ 22 января 2019

Мне нужно получить данные из таблицы «Пользователь и адрес», у меня есть таблица «Пользователь» и «Таблица адресов», между ними есть связь один ко многим, но она не работает должным образом. Когда я пытался получить данные от пользователя и добавить адрес какопция включения, но она не работает, см. мой код:

Модель пользователя:

"use strict";

const appConst = require("./../utils/app-const");

module.exports = (sequelize, DataTypes) => {
const User = sequelize.define("User", {
    id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: DataTypes.INTEGER,
    },
    companyId: {
        type: DataTypes.INTEGER,
        field: "company_id",
        references: {
            model: "Companies", // name of Target model
            key: "id", // key in Target model that we're referencing
        },
    },
    type: {
        type: DataTypes.TINYINT,
        validate: {
            isInt: true,
            notIn: [appConst.userType.arrayList,],
        },
    },
    firstName: {
        type: DataTypes.STRING,
        field: "first_name",
        validate: {
            len: {
                args: [0, 30,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",30),
            },
        },
    },
    lastName: {
        type: DataTypes.STRING,
        field: "last_name",
        validate: {
            len: {
                args: [0, 30,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",30),
            },
        },
    },
    username: {
        type: DataTypes.STRING,
        validate: {
            notEmpty: {
                args: true,
                msg: "Name " + appConst.appValidatorMsgs.NOT_EMPTY,
            },
            len: {
                args: [0, 40,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",40),
            },
        },
    },
    email: {
        type: DataTypes.STRING,
        validate: {
            notEmpty: {
                args: true,
                msg: "Name " + appConst.appValidatorMsgs.NOT_EMPTY,
            },
            isEmail: {
                args: true,
                msg: "Email " + appConst.appValidatorMsgs.IS_EMAIL,
            },
            len: {
                args: [0, 40,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",40),
            },
        },
    },
    password: {
        type: DataTypes.STRING,
        validate: {
            notEmpty: {
                args: true,
                msg: "Name " + appConst.appValidatorMsgs.NOT_EMPTY,
            },
            len: {
                args: [0, 64,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",64),
            },
        },
    },
    // gender: {
    //  type: DataTypes.ENUM,
    //  values: appConst.gender.arrayList,
    //  validate: {
    //      notIn: [appConst.gender.arrayList,],
    //  },
    // },
    dob: {
        type: DataTypes.DATE,
        validate: {
            isDate: true,
            len: {
                args: [0, 100,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",100),
            },
        },
    },
    photo: {
        type: DataTypes.STRING,
        validate: {
            len: {
                args: [0, 20,],
                msg: "Name " + appConst.appValidatorMsgs.LEN.replace("@len",20),
            },
        },
    },
    isActive: {
        type: DataTypes.BOOLEAN,
        field: "is_active",
        defaultValue: true,
    },
    verified: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
    },
    rememberToken: {
        type: DataTypes.STRING,
        field: "remember_token",
    },
    createdAt: {
        allowNull: false,
        type: DataTypes.DATE,
        field: "created_at",
    },
    updatedAt: {
        allowNull: false,
        type: DataTypes.DATE,
        field: "updated_at",
    },
}, {
    hooks: {
        beforeCreate: () => {
            // Do other stuff
        },
        afterCreate: () => {
            // Do other stuff
        },
    },
});

/*// Method 3 via the direct method
User.beforeCreate((user, options) => {
    return hashPassword(user.password).then(hashedPw => {
        user.password = hashedPw;
});*/

// don't use camelcase for automatically added attributes but underscore style
// so updatedAt will be updated_at
underscored: true,

/**
 * Associations
 * @param models
 */
User.associate = (models) => {
    // HasMany: associations can be defined here
    User.hasMany(models.Job,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});//Job Poster
    User.hasMany(models.JobRequest,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    User.hasMany(models.Address,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});

    // HasOne: associations can be defined here
    // Company.hasOne(models.CompanySetting,{foreignKey: "company_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    User.hasOne(models.Worker,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    User.hasOne(models.VerificationToken,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    // User.hasOne(models.Address,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});

    // BelongsTo: associations can be defined here
    User.belongsTo(models.Company,{foreignKey: "company_id",onDelete: "CASCADE",onUpdate: "SET NULL",});

};
return User;

};

Модель адреса

"use strict";

const appConst = require("./../utils/app-const");

module.exports = (sequelize, DataTypes) => {
const Address = sequelize.define("Address", {
    id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: DataTypes.INTEGER,
    },
    companyId: {
        type: DataTypes.INTEGER,
        field: "company_id",
        references: {
            model: "Companies", // name of Target model
            key: "id", // key in Target model that we're referencing
        },
    },
    userId: {
        type: DataTypes.INTEGER,
        field: "user_id",
        references: {
            model: "Users", // name of Target model
            key: "id", // key in Target model that we're referencing
        },
    },
    jobId: {
        type: DataTypes.INTEGER,
        field: "job_id",
        references: {
            model: "Jobs", // name of Target model
            key: "id", // key in Target model that we're referencing
        },
    },
    phNo: {
        type: DataTypes.STRING,
        field: "ph_no",
        validate: {
            // max: 15,
            len: {
                args: [0, 15,],
                msg: "phNo " + appConst.appValidatorMsgs.LEN.replace("@len",15),
            },
        },
    },
    name: {
        type: DataTypes.STRING,
        field: "name",
        validate: {
            len: {
                args: [0, 124,],
                msg: "Address " + appConst.appValidatorMsgs.LEN.replace("@len",124),
            },
        },
    },
    city: {
        type: DataTypes.STRING,
        field: "city",
        validate: {
            len: {
                args: [0, 70,],
                msg: "City " + appConst.appValidatorMsgs.LEN.replace("@len",70),
            },
        },
    },
    state: {
        type: DataTypes.STRING,
        field: "state",
        validate: {
            len: {
                args: [0, 70,],
                msg: "State " + appConst.appValidatorMsgs.LEN.replace("@len",70),
            },
        },
    },
    country: {
        type: DataTypes.STRING,
        field: "country",
        validate: {
            len: {
                args: [0, 70,],
                msg: "Country " + appConst.appValidatorMsgs.LEN.replace("@len",70),
            },
        },
    },
    zip: {
        type: DataTypes.STRING,
        field: "zip",
        validate: {
            len: {
                args: [0, 12,],
                msg: "zip " + appConst.appValidatorMsgs.LEN.replace("@len",12),
            },
        },
    },
    geoLat: {
        type: DataTypes.DECIMAL,
        field: "geo_lat",
    },
    geoLng: {
        type: DataTypes.DECIMAL,
        field: "geo_lng",
    },

},{
    // don't forget to enable timestamps!
    timestamps: false,
});

// don't use camelcase for automatically added attributes but underscore style
// so updatedAt will be updated_at
underscored: true,



/**
 * Associations
 * @param models
 */
Address.associate = (models) => {
    // HasMany: associations can be defined here
    // Company.hasMany(models.User,{foreignKey: "company_id",onDelete: "CASCADE",onUpdate: "SET NULL",});


    // HasOne: associations can be defined here
    // Company.hasOne(models.CompanySetting,{foreignKey: "company_id",onDelete: "CASCADE",onUpdate: "SET NULL",});


    // BelongsTo: associations can be defined here
    Address.belongsTo(models.Company,{foreignKey: "company_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    Address.belongsTo(models.User,{foreignKey: "user_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
    Address.belongsTo(models.Job,{foreignKey: "job_id",onDelete: "CASCADE",onUpdate: "SET NULL",});
};
return Address;

};

Как я получаю данные и где происходит ошибка с ошибкой:

const User = sequelize.import("./../../models/user");
const Address = sequelize.import("./../../models/address");
return await User.findOne({
    where: { id: userId,},
    // include: ["Address",],
    include: [{model: User.associate.Addresses,},],
}).then(async (user) => {
    console.log("user.models");
    await console.log(user.address);
    // console.log(user.__proto__);
    return {
        statusCode: appConst.httpCodes.SUCCESS,
        body: JSON.stringify({
            success: false,
            error: true,
            message: "Success!",
            entity: user,
        }),
    };
}).catch(err => ({
    // statusCode: err.statusCode || 
appConst.httpCodes.INTERNAL_SERVER_ERROR,
    statusCode: err.statusCode || appConst.httpCodes.INVALID_DATA,
    headers: appConst.commonResponseHeaders,
    // body: JSON.stringify({ stack: err.stack, message: err.message, }),
    body: JSON.stringify({
        success: false,
        error: true,
        message: "Invalid data!",
        errorMessages: [err.message,],
    }),
}));

при использованииas ... include: [Address,] ...

Сообщение об ошибке:

Адрес не связан с пользователем!

при использовании в качестве ... include: ["Address",] ... Сообщение об ошибке:

Ассоциация с псевдонимом \ "Адрес \" не существует

Я также пытался: ... include: [{model: Address,},], ... Сообщение об ошибке:

Адрес не связанПользователю!

Я был бы благодарен за помощь, в противном случае мне пришлось бы оставить Sequelize, потому что мой проект застрял для этого.

Обновленный код: I change my fetching code

const User = sequelize.import("./../../models/user");
const Address = sequelize.import("./../../models/address");
return await User.findOne({
where: { id: userId,},
    include: ["Address",],
}).then(async (user) => {
....

To

var db = require("./../../models/index");
const User = db.User;
const Address = db.Address;
return await User.findOne({
    where: { id: userId,},
    // include: ["Address",],
    include: [{model: Address,},],
}).then(async (user) => {
....

Тогда сообщение об ошибке изменено

Неизвестный столбец'User.user_id' в списке полей

Так что теперь проблема в том, что этот столбец не существует в атрибутах модели пользователя

Я до сих пор не понимаю, почему User.user_id всписок полей, но в любом случае

Я делаю дальнейшие изменения в своем коде, т.е. я добавил attributes: ["id",..], в частности:

 return await User.findOne({
    attributes: ["id", "email", "password", "username", "firstName", 
    "lastName", "gender", "dob", ],
    where: { id: userId,},
    // include: ["Address",],
    include: [{model: Address,},],
}).then(async (user) => {

, и он отлично работает.

Пожалуйста, не ставьтеэтот вопрос в дубликат, потому что я все перепробовал, тогда я отправлю этот вопрос для справки

...