Понимание ассоциаций в Sequelize - PullRequest
3 голосов
/ 14 мая 2019

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

Вот мои модели.

models / user.js

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      id: {
        type: DataTypes.INTEGER(11),
        allowNull: false,
        primaryKey: true,
        field: "id"
      },
      username: {
        type: DataTypes.STRING(20),
        allowNull: false,
        field: "username"
      },
      fullname: {
        type: DataTypes.STRING(60),
        allowNull: false,
        field: "fullname"
      },
      createdat: {
        type: DataTypes.DATE,
        allowNull: false,
        field: "createdat"
      },
      updateat: {
        type: DataTypes.DATE,
        allowNull: true,
        field: "updateat"
      },
      deletedat: {
        type: DataTypes.DATE,
        allowNull: true,
        field: "deletedat"
      }
    },
    {
      tableName: "users",
      timestamps: false
    }
  );

  User.associate = function(models) {
        models.User.hasMany(models.Ticket),
        { as: "createdbyname", foreignKey: "createdby" };
  };
  return User;
};

models / ticket.js

module.exports = (sequelize, DataTypes) => {
  const Ticket = sequelize.define(
    "Ticket",
    {
      id: {
        type: DataTypes.INTEGER(11),
        allowNull: false,
        primaryKey: true,
        field: "id"
      },
      details: {
        type: DataTypes.STRING(45),
        allowNull: true,
        field: "details"
      },
      assignedto: {
        type: DataTypes.INTEGER(11),
        allowNull: true,
        field: "assignedto"
      },
      createdby: {
        type: DataTypes.INTEGER(11),
        allowNull: true,
        field: "createdby"
      },
      createdat: {
        type: DataTypes.DATE,
        allowNull: false,
        field: "createdat"
      },
      updatedat: {
        type: DataTypes.DATE,
        allowNull: true,
        field: "updatedat"
      },
      deletedat: {
        type: DataTypes.DATE,
        allowNull: true,
        field: "deletedat"
      }
    },
    {
      tableName: "tickets",
      timestamps: false
    }
  );

  Ticket.associate = function(models) {
        models.Ticket.belongsTo(models.User,
            { foreignKey: "createdby" });
  };
  return Ticket;
};

В моем обработчике маршрутаЯ вызываю User.findAll следующим образом:

  models.User.findAll({
    include: [models.Ticket]
  })

Результат, который я ожидаю увидеть, - это запрос, который выглядит следующим образом:

SELECT 
    `User`.`id`,
    `User`.`username`,
    `User`.`fullname`,
    `User`.`createdat`,
    `User`.`updateat`,
    `User`.`deletedat`,
    `Tickets`.`id` AS `Tickets.id`,
    `Tickets`.`details` AS `Tickets.details`,
    `Tickets`.`assignedto` AS `Tickets.assignedto`,
    `Tickets`.`createdby` AS `Tickets.createdby`,
    `Tickets`.`createdat` AS `Tickets.createdat`,
    `Tickets`.`updatedat` AS `Tickets.updatedat`,
    `Tickets`.`deletedat` AS `Tickets.deletedat`
FROM
    `users` AS `User`
LEFT OUTER JOIN
    `tickets` AS `Tickets` ON `User`.`id` = `Tickets`.`createdby`

Запрос, который я вижу запущенным вконсоль:

SELECT 
    `User`.`id`,
    `User`.`username`,
    `User`.`fullname`,
    `User`.`createdat`,
    `User`.`updateat`,
    `User`.`deletedat`,
    `Tickets`.`id` AS `Tickets.id`,
    `Tickets`.`details` AS `Tickets.details`,
    `Tickets`.`assignedto` AS `Tickets.assignedto`,
    `Tickets`.`createdby` AS `Tickets.createdby`,
    `Tickets`.`createdat` AS `Tickets.createdat`,
    `Tickets`.`updatedat` AS `Tickets.updatedat`,
    `Tickets`.`deletedat` AS `Tickets.deletedat`,
    `Tickets`.`UserId` AS `Tickets.UserId`
FROM
    `users` AS `User`
LEFT OUTER JOIN
    `tickets` AS `Tickets` ON `User`.`id` = `Tickets`.`UserId`;

Обратите внимание на разницу в предложении LEFT OUTER JOIN.Это выдает ошибку следующим образом:

Unhandled rejection SequelizeDatabaseError: Unknown column 'Tickets.UserId' in 'field list'

Мне нужна помощь, чтобы выяснить, где я здесь ошибся.

1 Ответ

2 голосов
/ 14 мая 2019

При определении ассоциаций, таких как belongsTo, вы можете указать foreignKey и targetKey. foreignKey соответствует полю в исходной таблице (помните, синтаксис sourceModel.belongsTo(targetModel, options)). targetKey соответствует полю в целевой таблице.

В вашем случае вы допустили ошибку в ассоциации в файле models / ticket.js , который вы использовали:

models.Ticket.belongsTo(models.User, { foreignKey: "createdby" });

Здесь foreignKey ссылается на исходную таблицу Ticket. Следовательно, вы указываете Sequelize использовать поле createdBy для таблицы Ticket и значение по умолчанию (первичный ключ) для таблицы User. Поскольку createdBy не существует в Ticket, Sequelize возвращается к случаю по умолчанию, где он использует Ticket.UserID.

Чтобы исправить вашу связь (и запрос), вам нужно обновить belongsTo до следующего:

models.Ticket.belongsTo(models.User, { targetKey: "createdby" });
...