---
lang: zh
tags: backend,sequelize
---
# Sequelize 初學
[官方文件](https://sequelize.org/v5/manual/getting-started.html)
[別人翻譯的中文](https://itbilu.com/nodejs/npm/sequelize-docs-v5.html)
:::info
搭配 Express 架設後端 Server 請看: [Express 網頁後端建立](https://hackmd.io/4Sx0rDgETyCDepeh2fmL1g)
:::
## 安裝
先安裝 sequelize
```
$ npm install --save sequelize
```
然後根據資料庫使用不同的依賴
```
$ npm install --save pg pg-hstore # Postgres
$ npm install --save mysql2
$ npm install --save mariadb
$ npm install --save sqlite3
$ npm install --save tedious # Microsoft SQL Server
```
## 操作
### 基本連線
```javascript
const Sequelize = require('sequelize');
const config = require('../config/database');
const sequelize = new Sequelize(config.database, config.username, config.password, {
logging: console.log,
host: config.host,
port: config.port,
dialect: 'mysql',
pool: {
max: 10,
min: 0,
idle: 30000,
},
});
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch((err) => {
console.error('Unable to connect to the database: ', err);
});
```
+ logging: 指定紀錄 log 的方式,可以指定一個 callback
### 建立 Model
想成是用 js 在寫資料庫的 scheme,寫越詳細越好
```javascript
class UserModel extends Sequelize.Model {}
UserModel.init(
{
id: { type: Sequelize.INTEGER, primaryKey: true , autoIncrement: true },
name: { type: Sequelize.STRING, allowNull: false, defaultValue: '' },
gender:{ type: Sequelize.ENUM('male', 'female'), allowNull: false, defaultValue: 'male'},
account:{ type: Sequelize.STRING, allowNull: false }
},
{
sequelize: db,
modelName: 'user',
timestamps: false,
freezeTableName: true,
indexes:[{
unique: true,
fields: ['account']
}]
}
);
```
第一個 Object 參數是定義欄位名稱跟型態,第二個 Object 則是一些額外參數
+ sequelize: Sequelize 的 Instance,也就是連線的資料庫
+ modelName: 來源 table
+ timestamps(default: true): 預設會加上 createdAt 跟 updatedAt 這兩個欄位
+ freezeTableName(default: false): 預設會把單數欄位名稱改為複數 `user=>users`
+ indexes: 加入索引設定
### 建立 Model 關聯
```javascript
MemberModel.belongsTo(MemberTypeModel, { foreignKey: "member_type_id", targetKey: "id" });
MemberModel.belongsTo(MemberDepModel, { foreignKey: "member_dep_id", targetKey: "id" });
MemberModel.belongsTo(MemberCollegeModel, { foreignKey: "member_college_id", targetKey: "id" });
```
※還有其他關連方法尚未深入研究
### 同步 Model
```javascript
UserModel.sync();
```
若是連線資料庫中沒有這張表,便會自動建立,也有一些參數可以使用,[參考官方](https://sequelize.org/master/manual/model-basics.html#model-synchronization)。
### 取得資料
```javascript
UserModel.findAll({attributes:[...], where: {...}});
UserModel.findOne({attributes:[...], where: {...}});
UserModel.findByPk(pkValue);
```
[詳細 where 方法見官方](https://sequelize.org/v5/manual/models-usage.html#-code-findall--code----search-for-multiple-elements-in-the-database)。
+ attributes: 就是 SELECT 的欄位
#### JOIN
```javascript
UserModel.findAll({include: [{model:UserTypeModel, attributes:[...]}]});
```
#### where after join
```javascript
UserModel.findAll({
include: [
{model:UserTypeModel, attributes:[...]}
],
where: {
"$user_type.id$": 1
}
});
```
### Model Instance
[官方文件](https://sequelize.org/master/manual/model-instances.html)
[Sequelize 資料寫入](https://dwatow.github.io/2018/09-24-sequelize/sequelize-CUD-of-CRUD/)
```javascript
const jane = User.build({ name: "Jane" });
```
+ build: 建立 Model 實例,可以利用這個實例做到`新增,更新,刪除`,沒設定的欄位會給予預設值
+ 對於 Instance 的操作是真的會反映在資料庫上的
#### Instance 新增
```javascript
await jane.save();
```
或是直接
```javascript
const jane = await User.create({name:"Jane"}); // 等同於 build 之後 save
```
#### Instance 更新
```javascript
jane.name = "jaja"
jane.save();
```
若要放棄更改可以
```javascript
jane.reload(); // 可以重回最後一次 save 的狀態,事實上應該是回資料庫抓資料
```
#### Instance 刪除
```javascript
jane.destroy();
```
### 批次新增
```javascript
UserModel.bulkCreate([
{name:"jane"},
{name:"jaja"},
...
])
```
### 更新特定資料
```javascript
let updateDataRows = UserModel.update({name:"jane"},{where:{...}}) // 回傳被影響到的資料筆數
```
### 刪除特定資料
```javascript
UserModel.destroy({where:{...}});
```
### Migration
[Sequelize Migration](https://dwatow.github.io/2018/09-24-sequelize/sequelize-migration/)
※沒太多時間研究
### Cache
※沒太多時間研究