Sequelize 學習筆記

Sequelize 學習筆記

在 Node 中使用 MYSQL

  • 訪問 MYSQL 須要經過網絡請求給 MYSQL 服務器,對於 Node.js 程序,這個訪問 MySQL 服務器的軟件包一般稱爲 MySQL 驅動程序。不一樣的編程語言須要實現本身的驅動,MySQL 官方提供了各類多種的驅動程序。目前社區使用的比較普遍的 Mysql Nodejs 驅動程序是 mysqlmysql2 (與mysql的聯繫:兼容 mysql 大多數 API 以及性能更加優異)
  • node-mysql 是一個實現了 MySQL 協議的 Node.js JavaScript 客戶端,經過這個模塊能夠與 MySQL 數據庫創建鏈接、執行查詢等操做。若是直接使用 mysql 包提供的接口進行操做,編寫的代碼就比較底層,基本類同直接的 sql,例如查詢操做
var mysql = require('mysql')
// 創建與數據庫的鏈接
var connection = mysql.createConnection({
  host: 'example.com',
  user: 'example',
  password: 'secret-password'
})
// 經過 mysql提供的接口進行查詢
connection.query('SELECT * FROM project WHERE id = ?', ['1'], function( err, rows ) {
  if (err) {
    // error
  } else {
    for (let row in rows) {
      // 業務代碼
    }
  }
})
複製代碼

ORM (Object Relational Mapping)

  • ORM框架的做用就是就是能夠把關係型數據庫表結構 映射爲javascript對象。例如

Table projectjavascript

名稱 類型 容許空 默認值 主鍵 說明
id int(11) Y - Y
content text Y - N 項目描述
title varchar(90) Y - N 項目名稱
priority_status int(11) Y 1 N 優先級id
owner int(11) Y 0 N 項目經理(PM)id
team_id int(11) Y 0 N 小組id
process_status vint(11) Y - N 項目狀態
schedule double(11, 2) Y 0.00 N 項目進度
prepayDate date Y - N 預交時間
createDate date Y - N 建立時間
deadline date Y - N 截止時間
// 就能夠映射爲,表中每一列映射爲對象中一個鍵值對,每一行映射爲一個js對象。
  {
    id:'',
    content:'',
    title:'',
    priority_status:'',
    priority_status:'',
    owner:''
    ...
  }
複製代碼
  • 經過ORM框架,對數據庫進行 CURD時,不須要直接去書寫 SQL語句,而是經過操做對象,進而由框架轉化爲具體的SQL語句進行查詢,將對象轉化我表中的一條記錄。m
  • Sequelize 是Nodejs中比較經常使用的ORM框架

Sequelize基礎使用

創建數據庫鏈接html

let Sequelize = require("sequelize");
let sequelize = new Sequelize(
    'sample', // 數據庫名
    'root', // 用戶名
    'password', // 用戶密碼
    {
        dialect: 'mysql', // 數據庫使用mysql
        host: 'localhost', // 數據庫服務器ip
        port: 3306, // mysql默認端口
        define: {
            'underscored': true // 字段如下劃線(_)來分割(默認是駝峯命名風格)
        },
        pool: {
          max: 20, // 鏈接池最大鏈接數量
          min: 0, // 鏈接池最小鏈接數量
          idle: 10000 // 每一個線程最長等待時間
        }
    }
);

// freezeTableName: true,
複製代碼

定義模型java

  • 模型:用來表述(描述)數據庫表字段信息的對象,每個模型對象表示數據庫中的一個表,後續對數據庫的操做都是經過對應的模型對象來完成
// public define(modelName: String, attributes: Object, options: Object): Model
// modelName:模型名稱,自定義 attributes:模型中包含都數據,每個數據映射對應表中都每個字段 options:模型(表)的設置

var project = sequelize.define(
  'project', // 默認表名(通常這裏寫單數),生成時會自動轉換成複數形式。在模型訪問時的model.name
  {
    id: {
      type: Sequelize.INTEGER(11), // 字段類型
      allowNull: false, // 是否容許爲NULL
      primaryKey: true, // 字段是主鍵
      autoIncrement: true, // 是否自增
    },
    content: {
      type: Sequelize.TEXT,
      allowNull: true,
      unique: false // 字段是否UNIQUE
    },
    title: {
      type: Sequelize.STRING(90),
      allowNull: true,
      validate: { //模型驗證 當前字段值發生改變的時候進行驗證
        is: ["^[a-z]+$",'i'],     // 只容許字母
        not: ["[a-z]",'i'],       // 不能使用字母
        isEmail: true
      },
      field: 'project_title' // 數據庫中字段的實際名稱 
    }
  },
  {
    tableName: 'project', // 手動設置表的實際名稱
    timestamps: false, // 是否給每條記錄添加 createdAt 和 updatedAt 字段,並在添加新數據和更新數據的時候自動設置這兩個字段的值,默認爲true
    paranoid: true, // 設置 deletedAt 字段,當刪除一條記錄的時候,並非真的銷燬記錄,而是經過該字段來標示,即保留數據,進行假刪除,默認爲false
    freezeTableName: false, // 禁用修改表名; 默認狀況下,sequelize將自動將全部傳遞的模型名稱(define的第一個參數)轉換爲複數。 默認爲false
    indexes: [] // 定義表索引
  }
)

// 表同步:沒有就新建,有就不變
// project.sync();

// 表同步:沒有就新建,有就先刪除再新建
// project.sync({
// force: true
// });

複製代碼

node

  • 一個模型類對應一個表,一個模型實例對象(DAO)就是一條對應的表記錄,經過操做這個對象來關聯操做對應的表中的數據,操做模型類就是操做表,操做模型類對象就是操做該表中的某條記錄,既有以下對應關係
    • 模型類 - 表
    • 模型實例 - 記錄
    • DAO(Data Access Objec)這些實例對象擁有一系列操做數據的方法(saveupdatedestroy
// 建立模型實例對象 public static build(options: Object): Model | Model[]
// options:一個對象,對應的就是表中的字段(模型中定義的屬性),須要注意的是對該對象的操做不會當即反應到實際的數據庫中,須要經過後續的操做進行同步好比save
attr= {
    id:"test",
    content:"iscontent",
    titile:"istitle"
}
let projectInstance = Project.build(attr) // 建立實例對象

// 實例方法
projectInstance.save() // 驗證該實例,若是經過驗證,則持久化到數據庫中
projectInstance.update(updates: Object) // updates:要更新的字段,調用該方法等同於調用.set()而後.save()
projectInstance.destroy() // 銷燬該實例(假刪除或真刪除)



// public static create(values: Object, options: Object): Promise<Model>
// 構建一個新的模型實例,並進行保存。與build()方法不一樣的是,此方法除建立新實例外,還會將其保存到對應數據庫表中。
await Project.create(attr)

複製代碼

mysql

  • sequelize除了經過模型建立出來的實例對單條數據進行操做,也能夠經過模型類對整個對應的表進行操做
// 根據主鍵搜索單條記錄: 模型.findById(id: Number | String | Buffer) 
Project.findById(1);

// 根據條件搜索一條記錄: 模型.findOne(options: Object) 
Project.findOne({
    where:{id:1}
});
//搜索特定記錄或建立它(若是沒有對應記錄): 模型.findOrCreate(options: Object)

//在數據庫中搜索多個記錄,返回數據和總計數: 模型.findAll(findOptions: Object)
Project.findAll({
  where: { id:1, content: 'iscontent' }, // 搜索條件
  limit: 10, // 查詢記錄條數限制
  offset: 2, // 查詢時的偏移/起始位置,通常用於分頁查詢時
  order: [ 
      "id", //根據id排序
      ["id","desc"] //根據id倒序
  ],
  attributes:["title","owner"], //返回的字段
})

// 在數據庫中搜索多個記錄,返回數據和總計數: 模型.findAndCountAll(findOptions: Object)
// 與findAll相似,可是返回值包含 count 屬性 - 返回數據與總計數
let result = await Project.findAndCountAll({
    'limit': 20,
    'offset': 0
});
// 返回的result對象將包含2個字段:result.count是數據總數,result.rows是符合查詢條件的全部數據。

複製代碼
  • 限制字段
  • 字段重命名
  • where 子句
  • 複合過濾查詢
    • 在sequelize中,還存在一個Op對象,用於處理複雜的條件操做。
    • 常見的Op及解釋
// 限制查詢結果對象中的字段
let result = await Project.findAndCountAll({
    attributes:["title","owner"], 
});
// => { title: 'istitle', owner: 1 } 而不是返回全部的字段

// 字段重命名
let result = await Project.findAndCountAll({
    attributes:[ ["title","projectTitle" ],"owner"], 
});
// => { projectTitle: 'istitle', owner: 1 } 而不是返回全部的字段

// where 子句
let result = await Project.findAndCountAll({
    where:{
      id: [1, 2, 3],
      title: 'a',
      content: 'iscontent'
    }
});
// 查詢projects表中知足 (id ===1 || id ===2 || id ===3) && title === 'a' && content === 'iscontent' 條件的記錄

// 複合過濾
const Op = Sequelize.Op
Project.findAll({
  where: {
    title: 'a',
    id: { [Op.eq]: 1 }, // id爲1
    [Op.or]: [{ priority_status: [1, 2] }, { owner: { [Op.gt]: 10 } }] // (priority_status === 1 ||priority_status === 2)&& owner > 10
  }
})

// [常見的Op及解釋][5]
[Op.and]: {a: 5}           // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}]  // (a = 5 或 a = 6)
[Op.gt]: 6,                // id > 6
[Op.gte]: 6,               // id >= 6
[Op.lt]: 10,               // id < 10
[Op.lte]: 10,              // id <= 10
[Op.ne]: 20,               // id != 20
[Op.eq]: 3,                // = 3
[Op.not]: true,            // 不是 TRUE
[Op.between]: [6, 10],     // 在 6 和 10 之間
[Op.notBetween]: [11, 15], // 不在 11 和 15 之間
[Op.in]: [1, 2],           // 在 [1, 2] 之中
[Op.notIn]: [1, 2],        // 不在 [1, 2] 之中
[Op.like]: '%hat',         // 包含 '%hat'
[Op.notLike]: '%hat'       // 不包含 '%hat'
[Op.iLike]: '%hat'         // 包含 '%hat' (不區分大小寫) (僅限 PG)
[Op.notILike]: '%hat'      // 不包含 '%hat' (僅限 PG)
[Op.regexp]: '^[h|a|t]'    // 匹配正則表達式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達式/!~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]'    // ~* '^[h|a|t]' (僅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (僅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何數組['cat', 'hat'] - 一樣適用於 iLike 和 notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG數組重疊運算符)
[Op.contains]: [1, 2]      // @> [1, 2] (PG數組包含運算符)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG數組包含於運算符)
[Op.any]: [2,3]            // 任何數組[2, 3]::INTEGER (僅限PG)

複製代碼
  • 常見統計操做API
    • model.count({ where: {} }) 統計查詢個數
    • model.max(field, {where:{}}) 指定字段查詢最大值
    • model.min(field, {where:{}}) 指定字段查詢最小值
    • model.sum(field, {where: {}}) 求和

正則表達式

// public static update(values: Object, options: Object): Promise<Array<affectedCount, affectedRows>>

const result = await Project.update(
    {
      content: "newContent"
    },
    {
      where: {
        id: projectId,
        user_id: userId
      }
    }
  )
複製代碼

sql

  • model.destroy()
  • 須要注意的是,若是咱們開啓了paranoid模式,destroy的時候不會執行DELETE語句,而是執行一個UPDATE語句將deleted_at字段設置爲當前時間(一開始此字段值爲NULL)。咱們可使用model.destroy({force: true})來強制刪除,從而真正從表中刪除該條記錄。
// public destroy(options: Object): Promise<undefined>
 const result = await Project.destroy({
    where: {
      id: projectId,
      user_id: userId
    }
  })
複製代碼
相關文章
相關標籤/搜索