我试图理解sequelize如何在一个简单的例子中起作用:用户可以有很多帖子,帖子只能有一个用户。
第一个问题,我不知道是否必须使用迁移或带同步的模型来创建我的数据库。我的意思是,我必须在两者中加入相同的代码。这是用户表的迁移:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
allowNull: false,
type: Sequelize.STRING,
unique: true
},
password: {
allowNull: false,
type: Sequelize.STRING
},
email: {
allowNull: false,
type: Sequelize.STRING,
unique: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
这是Post模型:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
username: DataTypes.STRING,
password: DataTypes.STRING,
email: DataTypes.STRING
}, {
classMethods: {
associate: (models) => {
User.hasMany(models.Post);
}
}
});
return User;
};
我是否还必须指定用户名,电子邮件不能为空且在模型中必须是唯一的?
我该如何添加外键?在一个教程中,他们告诉我数据库自动添加外键但是如果我使用迁移,我认为它不起作用,我必须设置它吗?
答案 0 :(得分:2)
你是对的,你必须手动设置外键关系。
以下是官方文档链接:http://docs.sequelizejs.com/manual/tutorial/associations.html
您可以尝试以下代码:
var user_object = require('your_file_path');
var post_object = require('your_file_path');
user_object.hasMany(post_object, {
foreignKey: 'user_id',
sourceKey: 'user_id',
onDelete: 'cascade',
as:'Posts',
});
post_object.belongsTo(user_object, {
foreignKey: 'user_id',
sourceKey: 'user_id',
onDelete: 'cascade',
as:'Posts',
});
答案 1 :(得分:2)
对于您的版本“sequelize”:“^ 4.13.2”:
删除了classMethods和instanceMethods。
一个:
const Model = sequelize.define('Model', {
...
}, {
classMethods: {
associate: function (model) {...}
},
instanceMethods: {
someMethod: function () { ...}
}
});
新:
const Model = sequelize.define('Model', {
...
});
// Class Method
Model.associate = function (models) {
...associate the models
};
// Instance Method
Model.prototype.someMethod = function () {..}
请参阅官方文档Upgrade to V4
因此,对于关系,你应该完成这个步骤:
示例:
// models/index.js
import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';
import config from './config';
const sequelize = new Sequelize(config.db.url, config.db.options);
const DB = {};
// Import models
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
DB[model.name] = model;
});
// Here u should call class method for associations
Object.keys(DB).forEach((modelName) => {
if ('associate' in DB[modelName]) {
DB[modelName].associate(DB);
}
});
DB.sequelize = sequelize;
DB.Sequelize = Sequelize;
export default DB;
您可以将所有关系放入模型中。
用户:
// models/user.js
export default (sequelize, DataTypes) => {
const User = sequelize.define(
'users',
// Fields
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
// etc ...
},
// Options
{
timestamps: false, // <-- turn off timestamps
underscored: true, // <-- this option for naming with underscore. example: createdAt -> created_at
validate: {},
indexes: [],
},
);
User.associate = (models) => {
User.hasMany(models.post, {
// ...
});
User.hasMany(models.comment, {
// ...
});
// OR
models.user.hasMany(models.post, {
// ...
});
};
return User;
};
发布:
// models/post.js
export default (sequelize, DataTypes) => {
const Post = sequelize.define(
'posts',
// Fields
{
// ...
},
// Options
{
// ...
},
);
Post.associate = (models) => {
Post.belongsTo(models.user, {
// ...
});
// OR
models.post.belongsTo(models.user, {
// ...
});
};
return Post;
};
我是否还必须指定用户名,电子邮件不能为空 在模型中必须是唯一的吗?
是的,您应该定义模型中的所有内容,例如键,关系等等。因为您的应用程序使用模型来执行数据库操作。
我该如何添加外键?在一个教程中,他们说 我,数据库自动添加外键但我不认为 如果我使用迁移它是有效的,我必须设置它manualy no?
实际上,您无法在创建表和字段的迁移中定义复合键。
迁移的最佳做法应该是这样的:
所以你应该在迁移中手动添加所有内容。
要在迁移中添加索引,您应该使用queryInterface.addIndex
module.exports = {
up: queryInterface => queryInterface.addIndex(
'users',
{
unique: true,
fields: ['username', 'email'],
// if u want to rename u can use:
// name: 'whatever'
// by convention default name will be: table_field1_fieldN
},
),
down: queryInterface => queryInterface.removeIndex(
'users',
'users_username_email', // <-- this name by convention, but u can rename it
),
};
对于“键”,您应该使用queryInterface.addConstraint
主键
queryInterface.addConstraint('Users', ['username'], {
type: 'primary key',
name: 'custom_primary_constraint_name'
});
外键
queryInterface.addConstraint('Posts', ['username'], {
type: 'FOREIGN KEY',
name: 'custom_fkey_constraint_name',
references: { //Required field
table: 'target_table_name',
field: 'target_column_name'
},
onDelete: 'cascade',
onUpdate: 'cascade'
});
检查所有API References
答案 2 :(得分:1)
我真的只是重新构建你的代码。
//创建一个数据库配置文件
var Sequelize=require('sequelize');
var connection=new Sequelize('project','user','password',{
dialect:'mysql',
logging:false
});
connection.authenticate()
.then(() => {
console.log("Connected to database");
})
.catch(err => {
//console.error("Can't connect to database :(\n", err);
});
module.exports={
database:connection,
}
//您的用户架构文件
var database = require('your_file_path/DatabaseConnection').database;
var Sequelize = require('sequelize');
var Users = database.define('users', {
username: {
allowNull: false,
type: Sequelize.STRING,
unique: true
},
password: {
allowNull: false,
type: Sequelize.STRING
},
email: {
allowNull: false,
type: Sequelize.STRING,
unique: true
}
}, {
underscored: true
},hooks: {
beforeCreate: (user, option) => {
users.password = encrypto.encryptEntity(user.password);
//for automatic encryption of password
},
}
);
Users.sync();
//id, updated_at , and modified_at will be maintained by default
module.exports = {
Users
}
//你的帖子文件路径
var Posts = database.define('posts', {
post_content: {
allowNull: false,
type: Sequelize.STRING,
unique: true
}
}, {
underscored: true
});
//importing User
var Users = require('file_path')
Users.hasMany(Posts, {
foreignKey: 'user_id',
sourceKey: 'user_id',
onDelete: 'cascade',
as:'Posts',
});
Posts.belongsTo(Users, {
foreignKey: 'user_id',
sourceKey: 'user_id',
onDelete: 'cascade',
as:'Users',
});
// two way binding.
Posts.sync();
通过维护关系,您可以使用setter和getter方法轻松更新数据
Posts.setUsers(user_object);
//上面的代码会自动将user_id找到user_object
//对于您可以使用的选择查询:
Users.findOne({
where:{
id:user_id
},
include: [{
model: Posts,
attributes: ['post_content'],
as: "Posts"
}//this will bring every posts user has created
})
我认为上面的编码标准会让你的代码看起来更干净,对更大的项目更有帮助。
希望这有帮助。