Sequelize是Nodejs生态中一个比较出名的ORM框架。经过ORM框架,可使用对象来操做数据库表数据,提升了开发效率和代码可读性,也方便后期维护。
今天主要介绍经过迁移[Migration]
来建立数据库,表。node
迁移的好处,能够类比git。经过每次建立迁移文件,来支持更新,回滚数据库表结构,也方便协同开发,也避免人工手动去直接修改数据库,用代码自动管理。换个电脑,也不用去拷贝数据库,直接运行迁移就能够彻底恢复开发环境,极大减轻了心智负担。mysql
mkdir node_work cd node_work mkdir app npm init -y npm i sequelize-cli sequelize mysql2 koa
npx sequelize init
运行以后,会产生四个目录:git
config, migrations, models, seederssql
config:数据库
{ "development": { "username": "root", "password": "root", "database": "app_development", "host": "127.0.0.1", "port": 8889, "dialect": "mysql", "timezone": "+08:00" }, "test": { "username": "root", "password": null, "database": "app_test", "host": "127.0.0.1", "dialect": "mysql" }, "production": { "username": "root", "password": null, "database": "app_production", "host": "127.0.0.1", "dialect": "mysql" } }
环境env => {配置}
不一样环境,对应不一样的配置,也能够自定义环境,好比homenpm
env指的是process.env.NODE_ENV
,json
能够经过设置环境变量来改变,好比export NODE_ENV=production
;promise
迁移时候,也能够指定环境:npx sequelize db:migrate --env production
,来链接production对应配置的数据库cookie
建立数据库:session
npx sequelize db:create
说明
npx
是npm5.2以后,自带的一个命令。能够不用全局安装sequelize,使用时候,若是本地没有,就去npm仓库下载;下载完后或者本地已经下载过,就运行脚本命令。这样能够避免本地全局包过时,环境问题,每次都使用最新版本
migrations: 迁移文件
npx sequelize model:generate --name User --attributes username:string
执行后,会生成20180918055558-create-user.js
迁移文件,和models/user.js
模型文件
其余字段能够在迁移文件中补全,最后再运行npx sequelize db:migrate
,就能够在数据库中看到生成了users表
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, username: { type: Sequelize.STRING(20), allowNull: false }, password: { type: Sequelize.CHAR(32), allowNull: false }, createdAt: { allowNull: false, type: Sequelize.DATE }, updatedAt: { allowNull: false, type: Sequelize.DATE } }, { tableName: 'users', charset: 'utf8mb4', collate: 'utf8mb4_bin', define: { timestamps: true } }).then(() => { // 添加索引 return queryInterface.addIndex('users', { name: 'username', unique: true, fields: ['username'] }); }); }, // 回退时执行,删除表 down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Users'); } };
执行迁移:
npx sequelize db:migrate npx sequelize db:migrate:all
撤销迁移:
npx sequelize db:migrate:undo 最近一次的 npx sequelize db:migrate:undo:all npx sequelize db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js
--from, --to
参数,能够指定迁移文件
models: 模型文件
model:generate
生成的model都在这个目录中
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, username: { type: Sequelize.STRING(20), allowNull: false }, password: { type: Sequelize.CHAR(32), allowNull: false }, createdAt: { allowNull: false, type: Sequelize.DATE }, updatedAt: { allowNull: false, type: Sequelize.DATE } }, { tableName: 'users', charset: 'utf8mb4', collate: 'utf8mb4_bin', }).then(() => { return queryInterface.addIndex('users', { name: 'username', unique: true, fields: ['username'] }); }); }, down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Users'); } };
模型对象建立,默认会自动赋值,更新createdAt, updatedAt两个timestamps字段。下边会给出完整示例。
seeders: 填充数据文件
建立seed文件:
npx sequelize seed:generate --name demo-user
执行以后,会获得20180918090545-demo-user.js
'use strict'; const md5 = require('md5') module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.bulkInsert('Users', [ { username: 'Kimoo', password: md5('123456'), createdAt: new Date(), updatedAt: new Date(), }, { username: 'Reci', password: md5('123321'), createdAt: new Date(), updatedAt: new Date(), } ], {}); }, down: (queryInterface, Sequelize) => { /* Add reverting commands here. Return a promise to correctly handle asynchronicity. Example: return queryInterface.bulkDelete('Person', null, {}); */ return queryInterface.bulkDelete('Users', null, {}); } };
填充数据:
npx sequelize db:seed:all
撤销数据:
npx sequelize db:seed:undo 最近一次的 npx sequelize db:seed:undo --seed name-of-seed-as-in-data 具体某个 npx sequelize db:seed:undo:all
app.js
(async function() { const Koa = require('koa'); const KoaStaticCache = require('koa-static-cache'); const KoaBodyParser = require('koa-bodyparser'); const router = require('./routers/main'); const Session = require('koa-session'); const app = new Koa(); // app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256'); app.keys = ['app']; app.use( Session({ key: 'koa:sess', maxAge: 86400000, autoCommit: true, overwrite: true, httpOnly: true, signed: true, rolling: false, renew: false }, app) ); // app.use( async (ctx, next) => { // ctx.set('Access-Control-Allow-Origin','*'); // await next(); // } ); app.use( KoaStaticCache('./public', { prefix: 'public', gzip: true }) ); app.use( KoaBodyParser() ); app.use( router.routes() ); app.listen(8088); })();
models/index.js
'use strict'; const fs = require('fs'); const path = require('path'); const Sequelize = require('sequelize'); const basename = path.basename(__filename); const env = process.env.NODE_ENV || 'development'; const config = require(__dirname + '/../config/config.json')[env]; const db = {}; let sequelize; if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { sequelize = new Sequelize(config.database, config.username, config.password, config); } // 自动导入 models 文件夹下的全部文件,好比user.js这个模型文件 // 自动加载模型并执行 // let users = require('./users'); // let UsersModel = users(sequelize, Sequelize); // db[UsersModel.name] = UsersModel; // db['Users'] = UsersModel; // 下面经过fs自动加载全部的文件,并执行,同时生成的模型对象挂载到db对象下面,最后返回出去 fs .readdirSync(__dirname) .filter(file => { return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); }) .forEach(file => { const 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;
routers/main.js
const KoaRouter = require('koa-router'); const md5 = require('md5'); const Models = require('../models'); const Sequelize = require('sequelize'); const router = new KoaRouter(); router.post('/register', async ctx => { // console.log(ctx.request.body); let username = ctx.request.body.username.trim(); let password = ctx.request.body.password.trim(); let repassword = ctx.request.body.repassword.trim(); if (username=='' || password == '' || repassword == '') { return ctx.body = { code: 1, data: '用户名或密码不能为空' } } if (password != repassword) { return ctx.body = { code: 2, data: '两次输入的密码不一致' } } let user = await Models.Users.findOne({ where: { username } }); if (user !== null) { return ctx.body = { code: 3, data: '当前用户已经被注册了' } } let newUser = await Models.Users.build({ username, password: md5(password) }).save(); ctx.body = { code: 0, data: { id: newUser.get('id'), username: newUser.get('username') } } }); router.post('/login', async ctx => { let username = ctx.request.body.username; let password = ctx.request.body.password; let user = await Models.Users.findOne({ where: { username } }); if (user === null) { return ctx.body = { code: 1, data: '不存在该用户' } } if (user.get('password') !== md5(password)) { return ctx.body = { code: 1, data: '密码错误' } } // ctx.cookies.set('uid', user.get('id'), { // httpOnly: false // }); // 服务端发送一个约定好的cookie,来表示当前是登陆 // ctx.cookies.set('uid', user.get('id'), { // // httpOnly,表示当前的cookie是否容许客户端进行操做(js),若是为true,那么就表示这个cookie是能用户http协议的数据传输 // httpOnly: true, // signed: true // }); ctx.cookies.set('username', user.get('username'), { httpOnly: false }); ctx.session.uid = 1; ctx.body = { code: 0, data: { id: user.get('id'), username: user.get('username') } } }); }) module.exports = router;
能够在postman
中测试接口,地址http://localhost:8088/register
,注册用户
node app.js