【问题标题】:hasMany called with something that's not an instance of Sequelize.ModelhasMany 调用了不是 Sequelize.Model 实例的东西
【发布时间】:2017-10-19 15:05:29
【问题描述】:

正如你们所看到的,我的问题与标题描述有关,我创建了一个用户模型,并在 sequelize 中创建了一个照片模型,基本上一个用户可以拍摄许多照片,但每张照片只能与一个用户相关。

我的用户模型

    "use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var Foto = require('./Foto');

module.exports = function (sequelize, DataTypes) {
  var User = sequelize.define("User", {
    username: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isUnique: function (value, next) {
          var self = this;
          User.find({ where: { username: value } })
            .then(function (user) {
              // reject if a different user wants to use the same username
              if (user && self.id !== user.id) {
                return next('username already in use!');
              }
              return next();
            })
            .catch(function (err) {
              return next(err);
            });
        }
      }
    },

    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isUnique: function (value, next) {
          var self = this;
          User.find({ where: { email: value } })
            .then(function (user) {
              // reject if a different user wants to use the same email
              if (user && self.id !== user.id) {
                return next('Email already in use!');
              }
              return next();
            })
            .catch(function (err) {
              return next(err);
            });
        }
      }
    },

    typeOfUser: {
      type: DataTypes.INTEGER,
      allowNull:true,
      defaultValue:null
    },

    country: {
      type: DataTypes.STRING,
      allowNull:true,
      defaultValue:null
    },

    birthDate:{
      type: DataTypes.DATEONLY,
      allowNull:true,
      defaultValue:null
    },

    reports: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    },

    points: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    },

    password: {
      type: DataTypes.STRING,
      allowNull:false
    },

    numberFotos: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    }
  }, {
      classMethods: {
        generateHash: function (password) {
          return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
        },

      },
      instanceMethods: {
        validPassword: function (password) {
          return bcrypt.compareSync(password, this.password);
        }
      }


    });

  User.hasMany(Foto,{as: 'fotos', foreignKey: 'userId'})

  return Foto;
}

我的照片模型

"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var User = require('./User');


module.exports = function (sequelize, DataTypes) {
  var Foto = sequelize.define("Foto", {
    reports: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    },
    image: {
      type: DataTypes.STRING,
      allowNull: false
    },
    date: {
      type: DataTypes.DATE,
      allowNull:true
    },
    position: {
      type: DataTypes.RANGE,
      allowNull: true
    }
  });

  Foto.belongsTo(User, {foreignKey: 'userId'});

  return Foto;
}

【问题讨论】:

  • 当两个模型之间存在循环依赖时会发生此问题,例如在用户模型中放置 'const Photo = require('./User')' 而在照片模型中放置 'const User= require('./Photo')',要解决这个问题,有两个选项: 1- 将belongTo 和hasMany 定义为一个模型。 2-在每个模型中但在函数内部定义关系,并在 index.js 中调用此函数,例如在需要两个模型之后,就像在此 github.com/sequelize/sequelize/issues/10395 中发布的解决方案一样
  • 我的家伙@AhmadZahabi ...祝福你!!!这为我解决了问题。

标签: node.js postgresql sequelize.js


【解决方案1】:

我遇到了相同类型的问题。所有映射都按照文档中的说明完美完成。 然而,我收到了关于关联的问题。

Dorian 在本论坛给出了原因。
https://stackoverflow.com/a/60760296/16790144

我的做法:

models/company.js

const company = sequelize.define("company",{
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true,
  },
  companyName: {
    type: DataTypes.STRING,
    allowNull: false,
  }
});

export default company;

models/client.js

const Client = sequelize.define("client", {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true,
  },
  firstName: {
    type: DataTypes.STRING,
    allowNull: false,
  } 
});

export default Client;

models/clientCompany.js

const clientCompany = sequelize.define("client_company",{
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true,
  },
  companyId: {
    type: DataTypes.INTEGER
  },
  clientId: {
    type: DataTypes.INTEGER
  }
});

export default clientCompany;

models/index.js

import Company from './company';
import Client from './client';
import ClientCompany from './clientCompany';

Company.belongsToMany(Client, { through : ClientCompany });
Client.belongsToMany(Company, { through : ClientCompany });

export {
  Company,
  Client,
  ClientCompany,
};

handler.js 此文件包含业务逻辑。

import { Client, Company } from '../../models';

const company = await Company.findOne({
  where: { id: companyId },
  include: Client,
});

【讨论】:

    【解决方案2】:

    我有很多问题,但我转而使用以这种格式生成模型的 sequelize CLI,然后我发现创建关联要容易得多,因为索引文件会处理所有事情,而模型中的 static associate({ PersonalDetail })它本身已经需要你的模型在一个地方你需要做的就是解构它们,所以不需要文件顶部的任何东西。

    这个 youtube 视频真的帮助了我...https://www.youtube.com/watch?v=3qlnR9hK-lQ

    'use strict'
    const { Model } = require('sequelize')
    module.exports = (sequelize, DataTypes) => {
      class User extends Model {
        /**
         * Helper method for defining associations.
         * This method is not a part of Sequelize lifecycle.
         * The `models/index` file will call this method automatically.
         */
        static associate({ PersonalDetail }) {
          // define association here
          this.hasMany(PersonalDetail, {
            foreignKey: 'userId',
            //as: 'personalDetails',
          })
        }
      }
      User.init(
        {
          uuid: {
            type: DataTypes.UUID,
            defaultValue: DataTypes.UUIDV4,
          },
      
          moredata below: {
            type: DataTypes.STRING,
            allowNull: false,
          },
    
          //createdAt/updatedAt is defined in migration and updated automatically
        },
        {
          sequelize,
          tableName: 'users',
          modelName: 'User',
        }
      )
      return User
    }
    

    【讨论】:

      【解决方案3】:

      以上解决方案均不适用于我的场景(可能适用于其他设置)。我偶然发现了这篇文章,其中指出您必须在应用关联之前定义和导出模型。使用单独的 extra-setup.js 文件来定义关联,对我有用。

      https://github.com/sequelize/express-example/tree/master/express-main-example

      【讨论】:

        【解决方案4】:

        所以我收到了这个错误,我花了一些时间来处理这个错误。我意识到我得到了错误,因为我错误地引用了模型。 Sequelize 区分大小写,因此如果您使用 UpperCase 创建模型,请确保在整个引用过程中保持一致。

        我还要指出你可以试试这个

         User.hasMany(models.Foto ,{as: 'fotos', foreignKey: 'userId'})
        
        

        【讨论】:

          【解决方案5】:

          我遇到了类似的问题。有时可能是因为在您的 index.js 或 app.js 中,文件是按特定顺序加载的,例如,如果您在 A 和 B 之间有关系,则 A 先加载并引用 B,然后 B 依次引用 A ,错误将在 B 文件中抛出,因为 A 尚未完全定义/执行。

          解决方案是从模型文件中删除所有关联,在您的应用程序或 index.js 中需要它们,然后定义它们的关系。

          例子

          const entities = {
            A: require('./src/Entity/A'),
            B: require('./src/Entity/B'),
          };
          entities.A.belongsToMany(entities.B, {through: 'AB'});
          entities.B.belongsToMany(entities.A, {through: 'AB'});
          

          【讨论】:

          • 这正是发生在我身上的事情。感谢您分享您的解决方案。
          • @Dorian,我可以确认这个解决方案有效......但实施它有点令人沮丧(不要误会我的意思,我不是要冒犯你)。例如,如果您想了解EntityA,则必须检查./src/Entity/Aindex.js。如果您也可以将EntityA 的关联放在./src/Entity/A 中,那不是很好吗?最重要的是,如果您有许多具有关联的实体,index.js 可能会非常庞大​​。
          • 当我这样做时,它会显示hasOne is not a function。这太令人沮丧了
          【解决方案6】:

          您似乎需要在包含 1:many 关联的 1 部分的文件中定义关系的两端。也就是说,在您的情况下,“用户”文件。

          所以:

          User.hasMany(照片); Foto.belongsTo(用户);

          【讨论】:

            【解决方案7】:

            您可以在一个文件中定义两个模型的关系。它不会以这种方式抛出任何错误。

            在你的 Foto.js 中,你可以试试:

            ...
            
            Foto.belongsTo(User);
            User.hasMany(Foto);
            
            return Foto;
            

            【讨论】:

            • 我不认为所有模型都使用一个文件是一种好方法,尤其是在中型项目中。
            • “一个文件”是指涉及它们之间关系的“模型文件之一”。
            【解决方案8】:

            您无需在照片模型上声明关联:

            Foto.belongsTo(User, {foreignKey: 'userId'});
            

            当模型之间存在 1:N 关系时,您只需要引用“1”模型(在我们的例子中是 User 模型)中的 id,“N”模型(照片)中的 id。这样做:

            User.hasMany(Foto,{as: 'fotos', foreignKey: 'userId'})
            

            将在您的 Foto 表上创建一个名为“userId”的列,该列引用用户表。通过这种方式,两个模型都可以根据需要进行关联。

            【讨论】:

            • hmmm 谢谢你的好回答,我刚刚重读了该关联以获取与照片相关的用户
            • 你能详细说明为什么我不应该在子表模型中使用belongsTo吗?
            • 是否可以在父子架构中添加关系?
            • @KetavChotaliya 1. 不是说您“不能”使用 belongsTo ,理想情况下,您将 ide 外键放在依赖模型上的 1:N 关系。在这个具体的例子中,主要模型是User,因为没有User就不可能有Photos。 2. 是的,您可以在两个模型上添加关系。
            • 我们来看一个案例,1. 我想选择一张具有他父母关系的特定照片,比如我们案例中的用户详细信息。到时候怎么办? 2. 如果我可以在两个模型中定义关系,那么如上所述,sequalize 会抛出错误。
            猜你喜欢
            • 2017-04-19
            • 2022-01-04
            • 2020-09-21
            • 1970-01-01
            • 2018-04-20
            • 1970-01-01
            • 2019-05-21
            • 2020-09-26
            • 1970-01-01
            相关资源
            最近更新 更多