【问题标题】:Understanding Associations in Sequelize了解 Sequelize 中的关联
【发布时间】:2019-10-01 00:27:58
【问题描述】:

我正在尝试了解 Sequelize 中的关联。我从现有的数据库表开始,因此某些字段可能与 Sequelize 中的默认值不匹配。我使用 Sequelizer 直接从数据库生成我的模型。 我习惯于编写查询,但现在我正在尝试了解像 Sequelize 这样的 ORM 是如何工作的。

这是我的模型。

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'

我需要一些帮助来找出我哪里出错了。

【问题讨论】:

  • 我发现这个线程很有用,原因与 brilang 相同,我为了给我指出正确的方向来定义模型中的关联。下一步是如何填充关系。我正在阅读有关 setUser 或 addUser 的文档,但没有一个有效。帮助或建议将不胜感激。

标签: mysql node.js join sequelize.js associations


【解决方案1】:

定义关联时,例如belongsTo,您可以指定foreignKeytargetKeyforeignKey 对应于源表中的字段(请记住,语法是 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" });

【讨论】:

  • 谢谢。我得到了这个样本。我已经转移到其他图书馆,因为我正在试验和学习什么对我有用,什么对我没用。
【解决方案2】:

  Plant.findAll({
        include: Farm,
        order: [['name', 'ASC']]
        })
        .then(data=> {
            res.send(data)
        })
        .catch(err => {
            res.send(err)
            console.log(err);
            
        })
        
let arrQuery = [
      queryInterface.addColumn('farms', 'dayPlayed' , Sequelize.STRING),
      queryInterface.removeColumn('plants', 'dayPlayed' , Sequelize.STRING),
    ]
      return Promise.all(arrQuery)

【讨论】:

  • 一些文字解释会很有帮助,尤其是因为运行 sn-p 会产生错误
猜你喜欢
  • 2016-01-27
  • 2017-08-18
  • 2019-08-14
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 2018-03-08
  • 2017-07-31
相关资源
最近更新 更多