利用 Sequelize 來操做數據庫

利用傳說中的ORM技術,把關係數據庫的表結構映射到對象上,簡化數據庫操做。html

Published: 2019-3-01node

Sequelize 是一個基於 Prom 的 ORM for Node,面向熟悉 JavaScript 和使用 Node.js 進行後端開發的開發人員。在本篇文章中,將探討 Sequelize 的一些常見用例以及 利用 Sequelize-cli 完成相關的環境配置。mysql

  1. Sequelize 極簡入門教程;
  2. Sequelize-cli 完成 dev,test,prod 環境的配置,以及數據庫建立;
  3. Sequelize-cli 完成表結構的設計、遷移與數據填充;
  4. Sequelize 結合 Sequelize-cli 完成數據庫的增、刪、改、查;
  5. 總結。

Sequelize 極簡入門教程

本章代碼,heregit

ORM:Object-Relational Mapping,就是容許將關係數據庫映射到對象上,使得這些對象具備一些屬性和操做數據庫的方法,避免編寫 SQL 語句。github

Sequelize:Sequelize 是一款基於 Nodejs 功能強大的異步ORM框架,同時支持 PostgreSQL,MySQL,SQLite 等多種數據庫,很適合做爲Nodejs後端數據庫的存儲接口。sql

本節簡單利用 Sequelize 向數據庫中插入一條數據,方便後續理解 Sequelize-cli。數據庫

安裝


能夠利用 npmyarn 完成安裝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,並插入數據


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 的極簡介紹,主要想介紹一個映射的流向,方便後續理解,官網實例更加詳細

Sequelize-cli 完成 dev,test,prod 環境的配置,以及數據庫建立

本章代碼,here

與 Sequelize 相伴的有 Sequelize-cli 工具,Sequelize-cli 爲咱們提供了一系列好用的終端指令,來完成如下工做

  • 配置不一樣的環境的數據庫鏈接,例如dev、test、prod等;
  • 自動管理表對應的 Model;
  • 利用 migrations 完成數據庫的表結構的遷移;
  • 利用 seeders 完成數據庫的表內容的初始化。

首先安裝 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",
    ...
}
複製代碼

可建立開發環境、生產環境的的數據庫。

Sequelize-cli 完成表結構的設計、遷移與數據填充

本章代碼,here

表結構的設計、遷移都與 Migrations 相關

就像使用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'); */
  }
};
複製代碼

模塊暴漏出一個對象,包含着 updown 兩個方法,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 的表:

  • 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 來指定添充數據。

Sequelize 結合 Sequelize-cli 完成數據庫的增、刪、改、查

本章代碼,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 的操做,主要如下幾個

  • 查:findAllfindByPkfindCreateFindfindOrCreate.....

    const { users } = require("./models");
    
    (async () => {
        // 搜索多個實例
        const user = await users.findAll()
    	// 條件搜索name = 'John Doe'
        // const user = await users.findByPk(1)
    
        console.log(user)
    
        process.exit();
    })()
    複製代碼
  • 增:createbulkCreate....

    const { users } = require("./models");
    
    (async () => {
        await users.create({
            name: 'Yang'
        })
    
        process.exit();
    })()
    複製代碼
  • 刪:destroydrop刪表.....

    const { users } = require("./models");
    
    (async () => {
        await users.destroy({
            where: {
                name: 'Yang'
            }
        })
    
        process.exit();
    })()
    複製代碼
  • 改:upsertupdate.....

    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

相關文章
相關標籤/搜索