利用传说中的ORM技术,把关系数据库的表结构映射到对象上,简化数据库操做。html
Published: 2019-3-01node
Sequelize 是一个基于 Prom 的 ORM for Node,面向熟悉 JavaScript 和使用 Node.js 进行后端开发的开发人员。在本篇文章中,将探讨 Sequelize 的一些常见用例以及 利用 Sequelize-cli 完成相关的环境配置。mysql
本章代码,heregit
ORM:Object-Relational Mapping,就是容许将关系数据库映射到对象上,使得这些对象具备一些属性和操做数据库的方法,避免编写 SQL 语句。github
Sequelize:Sequelize 是一款基于 Nodejs 功能强大的异步ORM框架,同时支持 PostgreSQL,MySQL,SQLite 等多种数据库,很适合做为Nodejs后端数据库的存储接口。sql
本节简单利用 Sequelize 向数据库中插入一条数据,方便后续理解 Sequelize-cli。数据库
能够利用 npm
或 yarn
完成安装npm
// Using NPM
$ npm install --save sequelize
# And one of the following:
$ npm install --save pg pg-hstore
$ npm install --save mysql2
$ npm install --save sqlite3
$ npm install --save tedious // MSSQL
// Using Yarn
$ yarn add sequelize
# And one of the following:
$ yarn add pg pg-hstore
$ yarn add mysql2
$ yarn add sqlite3
$ yarn add tedious // MSSQL
复制代码
本文依赖 mysql
,因此json
$ npm install --save sequelize
$ npm install --save mysql2
复制代码
Sequelize 提供了两种链接数据库的方式小程序
const Sequelize = require('sequelize');
// 数据库相关参数
const sequelize = new Sequelize('database', 'username', 'password', {
// 所在ip
host: 'localhost',
// 所用端口
port: '端口',
// 所用数据库类型
dialect: 'mysql'|'sqlite'|'postgres'|'mssql',
// 请参考 Querying - 查询 操做符 章节
operatorsAliases: false,
// 设置链接池,所以若是您从单个进程链接到数据库,理想状况下应该只为每一个数据库建立一个实例
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
// 执行过程会log一些SQL的logging,设为false不显示
logging: false,
// SQLite only
storage: 'path/to/database.sqlite'
});
// 利用 uri 简易链接数据库
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
复制代码
本文所用数据库为 mysql,结合 sequelize.authenticate
来对链接进行测试,构建 index.js
const Sequelize = require('sequelize');
const sequelize = new Sequelize('users_dev', 'username', 'password', {
host: 'localhost',
port: 3306,
dialect: 'mysql',
operatorsAliases: false,
// logging: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
});
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
process.exit();
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
复制代码
利用 node index.js
运行该脚本,成功的会打印出 Connection has been established successfully.
。
Model 主要是用来完成与表之间的映射,主要利用 sequelize.define('name', {attributes}, {options})
完成 Model 的定义。咱们定义一个 User
模型对应 user
表。
const User = sequelize.define('user', {
// 即便表的结构也是Model的属性
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
}
});
复制代码
利用已经定义好的Model,能够完成对 user
表的插入数据操做
// force: true will drop the table if it already exists
User.sync({
force: true
}).then(() => {
// Table created
return User.create({
firstName: 'John',
lastName: 'Hancock'
});
}).then(() => {
process.exit()
})
复制代码
以上完成 Sequelize 的极简介绍,主要想介绍一个映射的流向,方便后续理解,官网实例更加详细。
本章代码,here
与 Sequelize 相伴的有 Sequelize-cli 工具,Sequelize-cli 为咱们提供了一系列好用的终端指令,来完成如下工做
首先安装 Sequelize-cli
npm i sequelize-cli -D
复制代码
在 package.json 中添加
"scripts": {
"init": "node_modules/.bin/sequelize init",
...
}
复制代码
运行 npm run init
命令,以后会发现,在目录下多了 config、models、migrations、seeders四个文件夹
├── config # 项目配置目录 | ├── config.json # 数据库链接的配置 ├── models # 数据库 model | ├── index.js # 数据库链接的样板代码 ├── migrations # 数据迁移的目录 ├── seeders # 数据填充的目录
本节只考虑配置相关的,也就是config文件夹下的内容,主要包含 config.json
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
复制代码
主要包含了 development、test、production,三个环境下的数据库信息。
以前我也是利用 config.json 来管理的,可是以后经过阅读基于 hapi 的 Node.js 小程序后端开发实践指南,发现利用 .env 文件来管理是一种更为优雅的方法。
安装 env2 插件,在当前目录下建立 .env 文件用于配置开发环境以及生产环境的基础信息。
npm i -D env2
复制代码
.env 内容,注字符串变量不须要''。
DB_USERNAME = username
DB_PASSWORD = password
DB_NAME = dataname
DB_NAME_PROD = prodDataname
DB_HOST = *.*.*.*
DB_PORT = *
复制代码
若是 git 非私密的,须要配置 .gitignore 的相关信息,在config文件下,建立config.js
require('env2')('./.env');
const {
env
} = process;
module.exports = {
"development": {
"username": env.DB_USERNAME,
"password": env.DB_PASSWORD,
"database": env.DB_NAME,
"host": env.DB_HOST,
"port": env.DB_PORT,
"dialect": "mysql",
"operatorsAliases": false,
},
"production": {
"username": env.DB_USERNAME,
"password": env.DB_PASSWORD,
"database": env.DB_NAME_PROD,
"host": env.DB_HOST,
"port": env.DB_PORT,
"dialect": "mysql",
"operatorsAliases": false,
}
}
复制代码
同时修改models文件夹下的index.js
// .json => .js
const config = require(__dirname + '/../config/config.js')[env];
复制代码
以上利用env2完成对开发环境,生产环境的config配置,添加 create
以及 create:prod
两条指令
"scripts": {
"init": "node_modules/.bin/sequelize init",
"create": "node_modules/.bin/sequelize db:create",
"create:prod": "node_modules/.bin/sequelize db:create --env production",
...
}
复制代码
可建立开发环境、生产环境的的数据库。
本章代码,here
就像使用Git / SVN管理源代码中的更改同样,可使用 Migration 来初始化数据库、或跟踪数据库更改,也就是说经过配置 Migration 文件能够将现有数据库迁移至另外一个状态,而且保存记录。
"scripts": {
...
"migration": "node_modules/.bin/sequelize migration:create --name create-examples-table",
"migration:prod": "node_modules/.bin/sequelize migration:create --name create-examples-table --env production"
...
}
复制代码
首先在开发环境下进行测试,执行 npm run migration
指令,以后会在 migrations 文件夹内建立一个20190301054713-create-examples-table.js 文件,内容为
'use strict';
module.exports = {
up: (queryInterface, DataTypes) => {
/* Example: return queryInterface.createTable('users', { id: DataTypes.INTEGER }); */
},
down: (queryInterface, DataTypes) => {
/* Example: return queryInterface.dropTable('users'); */
}
};
复制代码
模块暴漏出一个对象,包含着 up
、down
两个方法,up
用于定义表结构正向改变,down
则用于定义表结构的回退,对应其中的 return
,正向 createTable
,反向则是 dropTable
。
两个参数的定义:
queryInterface:用于定义Sequelize与所属数据库通讯的接口,包含一些API,例如createTable
用于建立表,dropTable
则用于撤销,addColumn
用于追加字段,removeColumn
则用于移除;
DataTypes:用于定义接口数据的类型。
queryInterface.createTable(...)
总体功能与 sequelize.define(...)
相似。简单设计以下表
'use strict';
module.exports = {
up: (queryInterface, DataTypes) => {
return queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
created_at: DataTypes.DATE,
updated_at: DataTypes.DATE,
});
},
down: (queryInterface) => {
return queryInterface.dropTable('users');
}
};
复制代码
添加以下指令
"scripts": {
...
"migrate": "node_modules/.bin/sequelize db:migrate",
"migrate:prod": "node_modules/.bin/sequelize db:migrate --env production",
...
}
复制代码
运行 npm run migrate
,会将 migrations 目录下的迁移行为定义,按时间戳的顺序,逐个地执行迁移描述,最终完成数据库表结构的自动化建立。会发现数据库examples_dev内建立了一张 SequelizeMeta 的表以及 users 的表:
queryInterface.createTable
建立的表。相应的也有 node_modules/.bin/sequelize db:migrate:undo
来撤销相应的迁移,这里就不展开介绍了。
主要利用 seeders 来在初始化数据表中中初始化一些基础数据,使用方式与数据库表结构迁移类似,添加以下指令。
"scripts": {
...
"seeder": "node_modules/.bin/sequelize seed:create --name init-users",
"seeder:prod": "node_modules/.bin/sequelize seed:create --name init-users --env production",
...
}
复制代码
运行 npm run seed
指令,则与数据迁移相同的是,seeders 文件夹下多了一个 ***init-users.js 文件,结构也和数据迁移相似。
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
/* Example: return queryInterface.bulkInsert('People', [{ name: 'John Doe', isBetaMember: false }], {}); */
},
down: (queryInterface, Sequelize) => {
/* Example: return queryInterface.bulkDelete('People', null, {}); */
}
};
复制代码
参数也相同,只不过一个是建立表,一个是建立数据,所利用的API不一样而已,例如。
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('users', [{
name: 'John Doe',
created_at: new Date(),
updated_at: new Date()
}], {});
},
down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('users', null, {});
}
};
复制代码
添加指令
"scripts": {
...
"seed": "node_modules/.bin/sequelize db:seed:all",
"seed:prod": "node_modules/.bin/sequelize db:seed:all --env production",
...
}
复制代码
也能够用 node_modules/.bin/sequelize db:seed --seed xxxxxxxxx-init-users.js
来指定添充数据。
本章代码,here
在第一节中,简单介绍了 User.create(...)
插入了一条数据,本节中介绍结合 Sequelize-cli 完成对数据库的增、删、改、查。
在 Models 文件夹下建立对应的模型文件 users.js,内容与第一节 sequelize.define(...)
相似
module.exports = (sequelize, DataTypes) => sequelize.define(
'users', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
tableName: 'users',
// 如下两个属性是针对createAt、updateAt这两个默认属性的,timestamps是不使用,而underscored
// 则是将createAt转化为create_at
// timestamps: false,
underscored: true,
}
)
复制代码
模型结构,与数据迁移相同,在 index.js 文件内引入模型
const { users } = require("./models");
复制代码
能够利用该 Model 完成对表 users 的操做,主要如下几个
查:findAll
、findByPk
、findCreateFind
、findOrCreate
.....
const { users } = require("./models");
(async () => {
// 搜索多个实例
const user = await users.findAll()
// 条件搜索name = 'John Doe'
// const user = await users.findByPk(1)
console.log(user)
process.exit();
})()
复制代码
增:create
、bulkCreate
....
const { users } = require("./models");
(async () => {
await users.create({
name: 'Yang'
})
process.exit();
})()
复制代码
删:destroy
、drop
删表.....
const { users } = require("./models");
(async () => {
await users.destroy({
where: {
name: 'Yang'
}
})
process.exit();
})()
复制代码
改:upsert
,update
.....
const { users } = require("./models");
(async () => {
await users.update({
name: 'Yange'
}, {
where: {
name: 'John Doe'
}
})
/* await users.upsert({ name: 'Sccc' }, { where: { name: 'Yange' } }) */
process.exit();
})()
复制代码
这篇主要是用来总结以前一直看到的零散知识,也是用来配置存底,防止本身忘了。以前用的 mongoose 到 Sequelize,感受本身一直在切换工具,却又没有很好地入门了解。以后应该是会选择一个点深刻了解下吧,对本身非常失望。
参考
http://docs.sequelizejs.com/class/lib/model.js~Model.html#static-method-upsert
https://juejin.im/book/5b63fdba6fb9a04fde5ae6d0/section/5b6c048e6fb9a04fdc36afc1