利用傳說中的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