问题:
外键关联会降低MySQL的并发量降低,sequelize.js想要联表查询,就必须创建关联关系。
但是用sequelize创建关联模型时,插件会自动为表创建关联的外键,这不是我们所期待的结果。
答案:
想要在不创建外键的情况下关联表,需要在创建表关联时加上一个属性constraints: false。
下面是具体代码:
// 建立一对一关联关系
Blogs.belongsTo(Users, {
// 创建外键 Blogs.userId -> Users.id
foreignKey: 'userId',
targetKey: 'id',
constraints: false
})
// 建立一对多关联关系
Users.hasMany(Blogs, {
foreignKey: 'userId',
sourceKey: 'id',
constraints: false
})
下面是完整的运行代码:
1. 创建Sequelize实例 - seq.js
const { Sequelize } = require('sequelize')
const sequelize = new Sequelize('koa2_weibo_db', 'root', 'root', {
host: '127.0.0.1',
dialect: 'mysql'
})
module.exports = sequelize
2. 创建模型 - model.js
const Sequelize = require('sequelize')
const seq = require('./seq.js')
// 创建 Users 模型,数据表名字是 Users
const Users = seq.define('users', {
// id 会自动添加
username: {
type: Sequelize.STRING(45),
allowNull: false
},
password: {
type: Sequelize.STRING(45),
allowNull: false
},
nickname: {
type: Sequelize.STRING(45)
}
},
{
tableName: 'users',
freezeTableName: true,
// timestamps: false,
})
// 创建 blogs
const Blogs = seq.define('blogs', {
title: {
type: Sequelize.STRING(45),
allowNull: false
},
content: {
type: Sequelize.TEXT,
allowNull: false
},
userId: {
type: Sequelize.INTEGER,
allowNull: false
}
},
{
tableName: 'blogs',
freezeTableName: true,
// timestamps: false,
}
)
// 建立一对一关联关系
Blogs.belongsTo(Users, {
// 创建外键 Blogs.userId -> Users.id
foreignKey: 'userId',
targetKey: 'id',
constraints: false
})
// 建立一对多关联关系
Users.hasMany(Blogs, {
foreignKey: 'userId',
sourceKey: 'id',
constraints: false
})
module.exports = {
Users,
Blogs
}
3. 同步模型 - sync.js
const seq = require('./seq.js')
require('./model.js')
seq.sync({force: true})
.then(() => {
console.log('sync ok')
process.exit()
})
4. 创建模拟数据和关联关系 - create.js
下面为一对多关系
users.id -> blogs.userId
const { Blogs, Users } = require('./model.js')
;(async function () {
// 创建用户
const data1 = []
console.time('start1')
for (let i = 0; i < 1000; i++) {
const zhangsan = await Users.create({
username: 'zhangsan' + (i + 1),
password: '123456',
nickname: '张三' + (i + 1)
})
data1.push(zhangsan.dataValues)
}
console.log('create:users', data1)
console.timeEnd('start1')
// 创建博客
const data2 = []
console.time('start2')
for (let i = 0; i < 10; i++) {
const article = await Blogs.create({
title: '文章' + (i + 1),
content: '我是content' + (i + 1),
userId: i + 1
})
data2.push(article.dataValues)
}
console.log('create:blogs', data2)
console.timeEnd('start2')
process.exit()
}())
5. 在不创建外键的情况下联表查询 - select.js
const { Blogs, Users } = require('./model.js')
const { resolve } = require('path')
const fs = require('fs')
// const Sequelize = require('Sequelize')
;(async function () {
const zhangsan = await Users.findAll({
attributes: ['id', 'username'],
include: [
{
model: Blogs,
required: true,
attributes: ['title'],
}
]
})
console.log(zhangsan.map(item => item.dataValues))
// 保存数据,方便查看
fs.writeFile(resolve(__dirname, 'data.json'), JSON.stringify(zhangsan.map(item => item.dataValues)), (err) => {
if (err) throw err
console.log('write ok')
})
}())
6. 执行顺序
# 同步模型
$ node sync.js
# 插入假数据
$ node create.js
# 联表查询
$ node select.js