【问题标题】:SequelizeEagerLoadingError: model is not associated to otherModelSequelizeEagerLoadingError:模型未关联到 otherModel
【发布时间】:2020-09-02 20:05:31
【问题描述】:

我在不同的论坛上看到过很多次这个问题,但我无法解决它。我将 Express 和 PostgreSQL 与 Sequelize 一起使用。

基本上我有两个模型:校园和学术经理。两者之间是一对一的关系,Campus 有一位学术经理。

我已经实现了两个模型和关联工作,我可以看到它在 postgres 服务器的 mi 数据库中显示。但是当我尝试实现我的校园获取请求时,我尝试包含经理信息,但没有成功。我一直收到同样的错误:

SequelizeEagerLoadingError: Academic_manager 未与校园关联!

我相信我的问题与 include

有关

这是我的代码 sn-ps:

campus.js

const campus = (sequelize, DataTypes) =>{
    const Campus = sequelize.define('campus', {
        name: {
            type: DataTypes.STRING,
            allowNull: false,
        },
        manager: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'academic_manager',
                key: 'id'
            }
        } 
    });    

    Campus.associate = models => {
        Campus.hasOne(models.Manager, { foreignKey: 'id'});
    }

    return Campus; 
};

export default campus;

academic_manager.js

const manager = (sequelize, DataTypes) =>{
    const Manager = sequelize.define('academic_manager', {
        name: {
            type: DataTypes.STRING,
            allowNull: false,
        },
        email: {
            type: DataTypes.STRING,
            allowNull: false
        } 
    });    

    Manager.associate = models => {
        Manager.belongsTo(models.Campus, { foreignKey: 'id'});
    }

    return Manager; 
};

export default manager;

还有get方法:

router.get('/', async (req, res) => {
    const campus = await req.context.models.Campus.findAll({
        include: [
            { model: req.context.models.Manager }
        ]
    });
    return res.send(campus);
}); 

获取请求在没有包含的情况下有效。我知道这种关联已经实现,因为当我描述我的校园表和经理表时,我有这个:

TABLE "campus" CONSTRAINT "campus_manager_fkey" FOREIGN KEY (manager) REFERENCES academic_manager(id)

【问题讨论】:

    标签: node.js postgresql express sequelize.js


    【解决方案1】:

    我的解决方案是我没有在模型索引中建立关联。我错过了这个:

    Object.keys(models).forEach(key => {
      if ('associate' in models[key]) {
        models[key].associate(models);
      }
    });
    

    永远记住要真正建立你的联想。

    【讨论】:

      【解决方案2】:

      您的模型定义有几个问题。 Sequelize 可能会混淆您是要关联模型,还是只是让它们引用彼此。

      您添加了实现关系约束的关联,还添加了引用键,旨在允许引用但不实现约束。

      可能想读:

      1. How to implement many to many association in sequelize
      2. https://sequelize.org/v5/manual/associations.html

      我已经评论了你的代码:

      campus.js

      const Campus = (sequelize, DataTypes) =>{
          const Campus = sequelize.define('Campus', {
              name: {
                  type: DataTypes.STRING,
                  allowNull: false,
              }
              // this is not correct.
              // read when to use reference key further below
              /* manager: {
                  type: DataTypes.INTEGER,
                  allowNull: false,
                  references: {
                      model: 'academic_manager',
                      key: 'id' 
                  }
      
              } */
          });    
      
          Campus.associate = models => {
              // Campus.hasOne(models.Manager, { foreignKey: 'id'});
              // foreignKey `id` is wrong. Your models already by default have `id`, which is their own.
              // you either define the name as `campus_id`, or just let sequelize handle it for you by not defining it at all and just use `Campus.hasOne(models.Manager)`.
              // but generally it's good practice to define, otherwise when you need it, you have to figure out what did sequelize help you name it as.
              // read: https://sequelize.org/master/manual/assocs.html#providing-the-foreign-key-name-directly
              Campus.hasOne(models.Manager, { foreignKey: 'campus_id'); // this means please inject `campus_id` into `Manager` 
          }
      
          return Campus; 
      };
      
      export default Campus;
      

      academic_manager.js

      const Manager = (sequelize, DataTypes) =>{
          const Manager = sequelize.define('Manager', {
              name: {
                  type: DataTypes.STRING,
                  allowNull: false,
              },
              email: {
                  type: DataTypes.STRING,
                  allowNull: false
              }
          });    
      
          Manager.associate = models => {
              // you don't define foreignKey here. because by doing so you are saying
              // you want to inject this foreignKey into `Campus`, which you are not.
              Manager.belongsTo(models.Campus);
          }
      
          return Manager; 
      };
      
      export default Manager;
      

      附加信息 - 何时使用此参考密钥?

      在关系数据库中,经验法则是,在任何 2 个模型之间,您应该只有 1 个路径,否则会形成 cyclic dependency,这可能会导致问题。

      假设你有第三个实体Location

      Campus.hasOne(Manager)
      Manager.belongsTo(Campus)
      
      Location.hasOne(Campus)
      Location.belongsTo(Campus)
      

      一切都很好。让我们暂时假设Manager 停留在Campus,您可以像这样找出他们的Location

      Manager -> Campus -> Location
      

      在您确定Manager 将始终保留在Location 中而不是其他任何地方的真实声明之前,并且您的应用程序更频繁地需要此信息之前,您会很想这样做:

      Location.hasOne(Manager)
      Manager.belongsTo(Location)
      

      你现在有了另一个路径Location -> Manager,你完成了Location -> Manager -> Campus -> Location -> Manager....的循环引用

      要打破这一点,您必须在哪个关系更重要或更常访问之间做出选择。在这种情况下,LocationManager 之间的关系似乎并不那么重要,那么继续使用Manager -> Campus -> Location

      但你想要蛋糕也吃掉它

      这里您不关联模型,只需使用引用键或使用constraints: false。阅读https://sequelize.org/master/manual/constraints-and-circularities.html

      constraints: false 是我通常的选择,因为它仍然为我提供了所有 sequelize 方法,就好像模型是关联的一样。但是要非常严格,您最多可以使用reference keys。然后进行手动联接,或使用您找到的引用键执行 2 次查询,以在其引用的表中定位其数据。

      【讨论】:

      • 感谢您的链接!我是续集的新手,所以这变得相当混乱。我试过你的代码更正,当我尝试在我的 GET 请求中使用 include 时仍然得到同样的错误 SequelizeEagerLoadingError: Academic_manager is not associated to Campus!。我尝试使用别名作为解释的链接之一:我从校园中删除了关联,并在管理器模型中添加了Manager.belongsTo(models.Campus, { as: 'managers' },并将 GET 请求修改为include: 'managers',但随后出现以下错误:Error: Association with校园里不存在别名“经理”
      • 我尝试再次在 Campus 中添加关联,但得到了同样的错误,指定了外键。而且不用写外键。
      • 尝试使您的所有型号名称保持一致。我认为您将 academic_manager 定义为 Manager 表。在你的同事中,它可能是 Models.academic_manager。
      • 我意识到这是一个非常愚蠢的错误,我忘了真正让关联发生。这是我的第一篇文章,谢谢你的回答,我应该删除我的问题吗?还是直接更新?
      • 保留一切,答案很明确,可能会帮助其他人(比如我)
      猜你喜欢
      • 2018-12-18
      • 2019-08-06
      • 2019-07-29
      • 1970-01-01
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-22
      相关资源
      最近更新 更多