我试图在两个表之间创建关联,我想添加一个外键。
两个模型是用户和公司
User.associate = (models) => {
User.belongsTo(models.Companies, { foreignKey: 'Company' });
};
我期望上面的代码是在用户表中添加一个Company ID字段,该字段引用了Companies表的Company ID。
在运行上面的代码时,我看不到创建任何其他列。我尝试检查是否在数据库中创建了外键关联,并且该关联也丢失了。
但是,如果我尝试在保留关联代码的同时添加具有相同名称的列,则会发生名称冲突。这似乎表明正在创建该关联,但我看不到它。
有人可以帮助我了解我在做什么错吗?感谢您的帮助!
models / company.js
module.exports = (sequelize, DataTypes) => {
var Company = sequelize.define('company', {
company: { type: DataTypes.STRING, primaryKey: true },
});
Company.associate = (models) => {
Company.hasMany(models.user, { as: 'users' });
};
Company.sync();
return Company;
};
models / user.js
const uuid = require('uuid/v4');
'use strict';
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define('user', {
id: { type: DataTypes.UUID, primaryKey: true },
name: { type: DataTypes.STRING, allowNull: false }
});
User.associate = (models) => {
User.belongsTo(models.company);
};
User.beforeCreate((user, _ ) => {
user.id = uuid();
return user;
});
User.sync();
return User;
};
models / index.js
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(__filename);
var env = process.env.NODE_ENV || 'development';
// var config = require(__dirname + '/../config/config.js')[env];
var db = {};
// if (config.use_env_variable) {
// var sequelize = new Sequelize(process.env[config.use_env_variable], config);
// } else {
// var sequelize = new Sequelize(config.database, config.username, config.password, config);
// }
const sequelize = new Sequelize('postgres://postgres:user@localhost:5432/mydb');
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
答案 0 :(得分:3)
我能够解决这个问题。
问题在于调用同步的顺序。在我的原始代码中,我在每个模型中调用了sync。即使我添加了选项force
和alter
,我仍然认为未添加外键。因此,我从模型内部删除了sync
代码,并将其添加到index.js
内部的单独循环中。
这给了我一个新问题。由于表应预先存在,因此创建表的顺序与外键工作的创建顺序不符。我通过手动提供sync
的顺序来解决了这个问题,现在我看到了正在创建的列。
总结一下:模型定义->模型关联->按顺序进行模型同步
SO的成员,谢谢您的建议。
答案 1 :(得分:1)
您的模型很好!您必须从模型文件中删除sync
,然后检查迁移文件中是否有带有foregin key
的外键的模型,
用于迁移用户:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.UUID
},
name: {
type: Sequelize.STRING
},
companyId: {
type: Sequelize.UUID,
references: {
model: 'Company',// company migration define
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
要从index.js和模型创建自动表,必须安装sequelize-cli
通过类型npm install --save sequelize-cli
然后必须运行此命令以在db中创建模型表
sequelize db:migrate
答案 2 :(得分:0)
通过使用foreignKey: 'Company'
告诉它与名为Company
的列关联。您通常还希望使用单表名,因此将company
与关联companies
一起使用。默认情况下,Sequelize将使用关联的主键,因此,如果要更改它或设置其他参数,只需指定foreignKey
。
const User = sequelize.define(
'user',
{ /* columns */ },
{ /* options */ }
);
User.associate = (models) => {
User.belongsTo(models.Company);
};
const Company = sequelize.define(
'company',
{ /* columns */ },
{ /* options */ }
);
Company.associate = (models) => {
Company.hasMany(models.User, { as: 'users' });
};
这将创建以下表Company (id)
和User (id, company_id)
。
查询与单个User
关联的所有Company
记录:
const user = await User.findAll({ include: { model: Company } });
/*
user = {
id: 1,
company_id: 1,
company: {
id: 1,
},
};
*/
通过Company
查询具有多个关联User
记录的所有users
记录:
const company = await User.findAll({ include: { model: User, as: 'users' } });
/*
company = {
id: 1,
users: [{
id: 1
company_id: 1,
}],
};
*/
答案 3 :(得分:0)
我的猜测是associate
方法没有被调用,因此,您的关联没有被创建。请记住,associate
不是内置的Sequelize方法,而只是社区使用的一种模式。 (有关this thread的更多信息)
有多种方法可以处理调用associate
,这是一个示例。您有一个models.js
文件来处理关联,并在主app.js
文件中对其进行了初始化。
// app.js (aka your main application)
const models = require('./models')(sequelize, DataTypes);
// models.js
module.exports = (sequelize, DataTypes) => {
const models = {
user: require('./userModel')(sequelize, DataTypes),
company: require('./companyModel')(sequelize, DataTypes)
};
Object.keys(models).forEach(key => {
if (models[key] && models[key].associate) {
models[key].associate(models);
}
});
};
// companyModel.js
module.exports = (sequelize, DataTypes) => {
var Company = sequelize.define('company', {...});
Company.associate = (models) => {
Company.hasMany(models.user, { as: 'users' });
};
Company.sync();
return Company;
};
// userModel.js
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define('user', {...});
User.sync();
return User;
};
也,仅供参考,您可能知道这一点,但是sync
仅应用于实验或测试,而不能用于生产应用。