在多个文件中对一个到多个关联进行续订

时间:2016-04-26 17:55:45

标签: node.js sequelize.js bluebird

我正在与sequ​​elize进行一对多的关联。大多数教程和文档都显示了在同一文件中定义两个模型的示例。 我目前有两个文件,第一个是city.js:

const Promise = require('bluebird');
var Country = require('./country');

var City = sequelize.define("City", {
  id: {
    type: DataTypes.INTEGER,
    field: 'id',
    primaryKey: true,
    autoIncrement: true
  },...
}, {
  freezeTableName: true,
  timestamps: false
});

City.belongsTo(Country, {foreignKey : 'countryId', as: 'Country'});

Promise.promisifyAll(City);
module.exports = City;

第二个文件country.js:

const Promise = require('bluebird');
var City = require('./city');

var Country = sequelize.define("Country", {
  id: {
    type: DataTypes.INTEGER,
    field: 'id',
    primaryKey: true,
    autoIncrement: true
  },
  ...
}, {
  freezeTableName: true,
  timestamps: false,
  paranoid: false
});

Country.hasMany(City, {foreignKey : 'countryId', as: 'Cities'});

Promise.promisifyAll(Country);
module.exports = Country;

当我导入两个模块并尝试实例化对象时:

var City = require('../model/external/city');
var CountryRepository = require('../repository/external/countryRepository');

CountryRepository.findById(1).then(function(country) {
    var city = City.build();
    city.name = 'Paris';
    city.setCountry(country);
    console.log('OK');
});

我收到以下错误:

  

抛出新错误(this.name +'。' +   Utils.lowercaseFirst(Type.toString())+'叫某事   那不是Sequelize.Model')

的实例

模型在从模型导出之前是否会被宣传,或者我遗漏了什么?

3 个答案:

答案 0 :(得分:6)

我不确定你的代码究竟是什么问题,需要运行它才能确定。

但是当您在寻找示例时,请查看Sequelize Github中的此示例。

它在不同文件中声明模型,并将它们关联到index.js

稍后您可以使用简单的model属性 model.Country 来引用您的其他模型:

City.belongsTo(model.Country, {foreignKey : 'countryId', as: 'Country'});

例如,user.js

答案 1 :(得分:0)

导出所有模型后,必须声明关联

我遇到了同样的问题!

答案 2 :(得分:0)

我创造了一种我认为非常好的技术,甚至允许跨外键组合唯一键。

我将举例说明一个基本的user.js模型类文件

models/user.js

const { Model, DataTypes } = require('sequelize');
module.exports = function(sequelize){
    class User extends Model {}
    return User.init({
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: {
          type: DataTypes.STRING,
          allowNull: false
      },
      trading_system_key: {
          type: DataTypes.STRING,
          allowNull: false
      },
    }, {
      sequelize,
      modelName: 'User',
      indexes: [{ unique: true, fields: ['trading_system_key'] }]
    });
};

这显示了一个简单的用户类示例,还没有关联,但下一个文件将使用它。

models/algorithm.js

const { Model, DataTypes } = require('sequelize');
const User = require('../models/user');

module.exports = function(sequelize){
    class Algorithm extends Model {}
    UserModel = User(sequelize);//@JA - Gets a defined version of user class

    var AlgorithmFrame = Algorithm.init({
        id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: DataTypes.STRING,
            allowNull: false,
        },
        user_Id: {
            type: DataTypes.INTEGER,
            references: { 
                model: UserModel,
                key: 'id',
            },
        }
    }, {
      sequelize,
      modelName: 'Algorithm',
      indexes: [{ unique: true, fields: ['name','user_id'] }]
    });

    return AlgorithmFrame
};

这个例子展示了如何创建外键引用而不必说belongsTo 或HasOne 等...当你需要创建复合键时,这会派上用场。

例如,注意我把 indexes: [{ unique: true, fields: ['name','user_id'] }]

这使得 name 和 user_id 不能相同(复合键)。因此,例如,如果名称是 Joe 并且 user_id 是 1,并且我尝试创建另一个具有相同详细信息的记录,它将拒绝它,但是如果我创建了名称为 Rachel 和 user_id 1 的内容,它将允许它,因为它只是唯一的如果两者相同。

据我所知,除非您以这种方式设置,否则不可能执行复合键。

这种技术的另一个优点是模型在一个单独的文件中并定义为类!

那么我该如何使用这些?

(在您的文件中,您定义了续集连接...) api.js

const { Sequelize, DataTypes, Model } = require('sequelize');
const User = require('../models/user');
const Algorithm = require('../models/algorithm');

const sequelize = new Sequelize('database', 'username', 'passwordhere', {
      host: 'db',
      dialect: 'mysql' /* one of 'mysql' | 'mariadb' | 'postgres' | 'mssql' */
    });

const UserModel = User(sequelize);
const AlogorithmModel = Algorithm(sequelize);

(async () => {
      try {
        await sequelize.authenticate();
        await UserModel.sync({ alter: true });
        await AlogorithmModel.sync({ alter: true });

        //Do something with the models now....
        //Etc...

      } catch (error) {
        console.error('Unable to connect to the database:', error);
      }

});

这种技术之所以有效,是因为类文件是如何定义的。在典型的软件开发中,您包含类并引用它并实例化它,但在这种情况下我们已经传入它的实例化版本

例如,您会注意到我在类文件中定义了 class user extends model {} 并且里面只是空的。然后我们返回类的实例化版本。当你以这种方式使用 module.exports 时,它实际上是在期待一个 sequelize 连接实例的参数。

这就是为什么在 api.js 文件中我说 const User = require('../models/user');,这会引用文件返回的“函数”。

该函数不会做任何事情,除非你将它传递给 sequelize,所以你看到的下一行......

const UserModel = User(sequelize);

通过这样做,您可以将模型放在单独的文件中,并将它们作为类,并且它们仍然可以具有关联甚至复合索引!

希望能帮到你。