學會Sequelize,讓你操作數(shù)據(jù)更絲滑!
本文來介紹 Sequelize,一個基于 Node.js 的 ORM(對象關(guān)系映射)工具,并詳細介紹其用法。Sequelize 用于在應(yīng)用中使用 JavaScript 來操作關(guān)系型數(shù)據(jù)庫,例如 MySQL、PostgreSQL 等。本文內(nèi)容較多,可作為 Sequelize 的參考手冊來閱讀。
開始使用
核心概念
Sequelize 是一個基于 JavaScript 的 ORM(對象關(guān)系映射)庫,用于在 Node.js 環(huán)境中與數(shù)據(jù)庫進行交互。它提供了一種方便、靈活的方式來管理數(shù)據(jù)庫,并將數(shù)據(jù)庫表映射為對象,使開發(fā)人員可以使用面向?qū)ο蟮木幊田L格來操作數(shù)據(jù)庫。
ORM(對象關(guān)系映射)是一種編程技術(shù),用于通過將對象和數(shù)據(jù)庫表之間建立映射關(guān)系,以更直觀的方式進行數(shù)據(jù)庫操作。Sequelize 通過將數(shù)據(jù)庫記錄映射為模型對象,使得開發(fā)人員可以使用 JavaScript 對象的方法和屬性來進行數(shù)據(jù)庫的增刪改查操作,而不需要編寫復(fù)雜的 SQL 查詢語句。
Sequelize 支持多種數(shù)據(jù)庫,包括 MySQL、PostgreSQL、SQLite 和 MSSQL 等,可以適應(yīng)各種不同的項目需求。它提供了豐富的功能,包括模型定義、關(guān)聯(lián)關(guān)系、事務(wù)處理、查詢構(gòu)建器等,可以幫助開發(fā)人員高效地進行數(shù)據(jù)庫操作。
使用 Sequelize,開發(fā)人員可以輕松地進行數(shù)據(jù)庫遷移、執(zhí)行復(fù)雜的查詢和聚合操作,并實現(xiàn)數(shù)據(jù)校驗和驗證等功能。此外,它還提供了鉤子函數(shù)、事件觸發(fā)和數(shù)據(jù)庫連接池等功能,以優(yōu)化數(shù)據(jù)庫訪問性能。
基本使用
要使用 Sequelize 來連接 MySQL 數(shù)據(jù)庫,需要進行以下步驟:
- 安裝 Sequelize 和 MySQL 驅(qū)動程序:
- 使用 npm 運行以下命令來安裝 Sequelize:npm install sequelize
- 安裝 MySQL:npm install mysql2
- 創(chuàng)建 Sequelize 實例和數(shù)據(jù)庫連接:
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
});
這里需要將 'database'、'username' 和 'password' 分別替換為 MySQL 數(shù)據(jù)庫的名稱、用戶名和密碼。還可以根據(jù)需要設(shè)置其他連接選項,例如 host 和 port。
- 定義模型:
const User = sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
// 其他屬性和選項
});
這里定義了一個名為 User 的模型,包含 username 和 email 屬性。
- 進行數(shù)據(jù)庫操作:
async function createUser() {
await sequelize.sync(); // 同步模型和數(shù)據(jù)庫
const user = await User.create({ username: 'John', email: 'john@example.com' });
console.log(user.toJSON());
}
createUser().catch(console.error);
這里首先調(diào)用 sequelize.sync() 方法來同步模型和數(shù)據(jù)庫,以確保模型在數(shù)據(jù)庫中存在。然后使用 User.create() 方法創(chuàng)建一個新用戶,并輸出其序列化后的 JSON 數(shù)據(jù)。
這只是 Sequelize 連接 MySQL 的基本用法,你還可以使用 Sequelize 提供的其他方法來執(zhí)行查詢、更新、刪除等操作,以及定義模型之間的關(guān)聯(lián)關(guān)系。下面會詳細介紹!
模型定義
在 Sequelize 中,模型(Model)是一種表示數(shù)據(jù)庫表結(jié)構(gòu)的抽象化概念。它定義了數(shù)據(jù)表的結(jié)構(gòu)和行為,包括表名、字段、關(guān)聯(lián)關(guān)系、數(shù)據(jù)校驗規(guī)則等。
Sequelize 模型允許通過編寫模型類來操作數(shù)據(jù)庫表,封裝了對數(shù)據(jù)庫的增刪改查等操作。每個模型類對應(yīng)一個數(shù)據(jù)庫表,并且模型類的實例代表數(shù)據(jù)庫表中的一條記錄。
創(chuàng)建模型
定義模型方法
可以使用sequelize.define() 方法來創(chuàng)建模型,它用于定義和創(chuàng)建模型,其基本語法如下:
sequelize.define(modelName, attributes, options)
參數(shù)說明:
- modelName:模型的名稱。
- attributes:模型的屬性定義,一個包含列名和數(shù)據(jù)類型的對象。
- options:模型的其他選項,例如表名、時間戳等。
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password');
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},
}, {
tableName: 'users',
timestamps: true,
});
// 創(chuàng)建用戶實例
User.create({ username: 'John', email: 'john@example.com' })
.then((user) => {
console.log(user.toJSON());
})
.catch(console.error);
這里使用 sequelize.define() 方法定義了一個名為 User 的模型。模型具有 id、username、email、createdAt 和 updatedAt 等屬性。我們還指定了表名為 'users',以及啟用了時間戳屬性。
定義模型步驟
在 Sequelize 中,創(chuàng)建模型的步驟如下:
- 配置 Sequelize 實例連接數(shù)據(jù)庫,確定數(shù)據(jù)庫的相關(guān)信息。
- 使用 sequelize.define 方法定義模型,并指定模型的名稱、字段和其他選項。
- 通過調(diào)用模型的 sync 方法將模型同步到數(shù)據(jù)庫中。
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
// 配置數(shù)據(jù)庫連接信息
});
// 定義模型
const User = sequelize.define('User', {
name: Sequelize.STRING,
email: Sequelize.STRING,
age: Sequelize.INTEGER,
});
// 同步模型到數(shù)據(jù)庫
(async () => {
try {
await sequelize.sync();
console.log('模型創(chuàng)建成功!');
} catch (error) {
console.error('模型創(chuàng)建失?。?, error);
} finally {
sequelize.close(); // 關(guān)閉數(shù)據(jù)庫連接
}
})();
記得在最后關(guān)閉 Sequelize 連接,避免資源泄漏。
注意,模型創(chuàng)建后只需調(diào)用 sequelize.sync 方法進行同步一次即可,后續(xù)對模型的修改不會自動同步到數(shù)據(jù)庫。如果想要更新現(xiàn)有的模型定義,可以使用 Sequelize 提供的遷移工具或手動修改數(shù)據(jù)庫表結(jié)構(gòu)。
定義模型參數(shù)
上面的例子只定義了字段的類型,其實還有很多屬性可以定義,下面來看一個例子:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
// 配置數(shù)據(jù)庫連接信息
});
const User = sequelize.define('User', {
name: {
type: Sequelize.STRING,
allowNull: false,
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0,
validate: {
min: 0,
},
},
});
在字段定義對象中,每個屬性表示一個字段。屬性的名稱是字段的名稱,屬性的值是字段的配置。下面來分別看看這些字段值。
type:參數(shù)類型
type 屬性用于指定模型字段的數(shù)據(jù)類型。以下是一些常見的數(shù)據(jù)類型選項:
- STRING:字符串類型。
- CHAR:字符型,允許存儲固定長度的字符串。
- TEXT:文本類型,適用于存儲大段文本數(shù)據(jù)。
- INTEGER:整數(shù)類型。
- BIGINT:大整數(shù)類型。
- FLOAT:浮點數(shù)類型。
- DOUBLE:雙精度浮點數(shù)類型。
- DECIMAL:十進制數(shù)類型。
- BOOLEAN:布爾類型。
- DATE:日期類型,不包括時間。
- TIME:時間類型,不包括日期。
- DATEONLY:僅日期類型。
- DATETIME:日期和時間類型。
- BLOB:二進制大對象類型,適用于存儲二進制數(shù)據(jù)。
- UUID:通用唯一識別碼類型。
此外,Sequelize 還支持將數(shù)據(jù)類型與修飾符結(jié)合使用,以提供更豐富的數(shù)據(jù)定義選項。例如:
- STRING(100):指定字符串類型的最大長度為 100 個字符。
- INTEGER.UNSIGNED:指定無符號整數(shù)類型。
- DECIMAL(10, 2):指定十進制數(shù)類型,并設(shè)置總共10位數(shù),其中包含2位小數(shù)。
數(shù)字類型
在 Sequelize 中,數(shù)字類型包括以下幾種:
- INTEGER:表示整數(shù)類型。可以使用 Sequelize.INTEGER 或 Sequelize.INTEGER(n) 來定義,其中 n 是整數(shù)的位數(shù)。
- BIGINT:表示長整數(shù)類型??梢允褂?nbsp;Sequelize.BIGINT 或 Sequelize.BIGINT(n) 來定義,其中 n 是長整數(shù)的位數(shù)。
- FLOAT:表示單精度浮點數(shù)類型??梢允褂?nbsp;Sequelize.FLOAT 或 Sequelize.FLOAT(n, m) 來定義,其中 n 是總位數(shù),m 是小數(shù)部分的位數(shù)。
- DOUBLE:表示雙精度浮點數(shù)類型??梢允褂?nbsp;Sequelize.DOUBLE 或 Sequelize.DOUBLE(n, m) 來定義,其中 n 是總位數(shù),m 是小數(shù)部分的位數(shù)。
- DECIMAL:表示任意精度的十進制數(shù)類型??梢允褂?nbsp;Sequelize.DECIMAL 或 Sequelize.DECIMAL(n, m) 來定義,其中 n 是總位數(shù),m 是小數(shù)部分的位數(shù)。
字符串類型
在 Sequelize 中,字符串類型有以下幾種選項可供選擇:
- STRING:表示普通的字符串類型??梢允褂?nbsp;Sequelize.STRING 來定義,默認最大長度為 255 個字符。
- CHAR:表示定長的字符串類型。你可以指定最大長度作為選項??梢允褂?nbsp;Sequelize.CHAR(length) 來定義,其中 length 是字符串的最大長度。
- TEXT:表示長文本類型??梢源鎯Ω箝L度的文本數(shù)據(jù)??梢允褂?nbsp;Sequelize.TEXT 來定義。
- UUID:表示 UUID 字符串類型,用于存儲全局唯一標識符??梢允褂?nbsp;Sequelize.UUID 來定義。
- ENUM:表示枚舉類型,用于存儲預(yù)定義的選項列表中的一個值。需要提供一個選項數(shù)組作為參數(shù)。可以使用 Sequelize.ENUM(values) 來定義,其中 values 是枚舉選項的數(shù)組。
- JSON:表示存儲 JSON 數(shù)據(jù)的字符串類型??梢允褂?nbsp;Sequelize.JSON 來定義。
- JSONB:表示存儲 JSONB(二進制格式的 JSON)數(shù)據(jù)的字符串類型(僅支持 PostgreSQL)??梢允褂?nbsp;Sequelize.JSONB 來定義。
日期類型
在 Sequelize 中,日期類型包括以下幾種:
- DATE:表示日期類型,不包含時間??梢允褂?nbsp;Sequelize.DATE 來定義。
- TIME:表示時間類型,不包含日期??梢允褂?nbsp;Sequelize.TIME 來定義。
- DATETIME:表示日期和時間類型??梢允褂?nbsp;Sequelize.DATE 或 Sequelize.DATETIME 來定義。
- NOW:表示當前時間??梢允褂?nbsp;Sequelize.NOW 來獲取當前時間的值。
- DATEONLY:表示只包含日期的類型,不包含時間??梢允褂?nbsp;Sequelize.DATEONLY 來定義。
- SMALLDATETIME:表示包含日期和時間的類型,時間精度較低。可以使用 Sequelize.SMALLDATETIME 來定義。
- TIMESTAMP:表示包含日期和時間的類型,時間精度高于 SMALLDATETIME??梢允褂?nbsp;Sequelize.TIMESTAMP 來定義。
UUID類型
在 Sequelize 中,UUID 類型用于表示一個全局唯一的標識符。Sequelize 支持以下幾種 UUID 類型:
- UUID:表示標準 UUID 字符串,長度為 36 個字符??梢允褂?nbsp;Sequelize.UUID 來定義。
- UUIDV1:表示基于時間戳和 MAC 地址生成的 UUID 字符串??梢允褂?nbsp;Sequelize.UUIDV1 來獲取該類型的默認值。
- UUIDV4:表示隨機生成的 UUID 字符串??梢允褂?nbsp;Sequelize.UUIDV4 來獲取該類型的默認值。
allowNull:是否可以為空
allowNull 是 Sequelize 中用于定義模型字段是否允許為空的屬性選項。
當 allowNull 設(shè)置為 true 時,表示該字段允許為空。這意味著在創(chuàng)建記錄或更新記錄時,可以將該字段設(shè)置為空值(null)。如果設(shè)置為 false,表示該字段不能為空。
defaultValue:默認值
defaultValue 用于定義模型字段默認值的屬性選項。
當創(chuàng)建記錄時,如果沒有提供該字段的值,則會使用 defaultValue 屬性定義的默認值。
primaryKey:主鍵值
primaryKey 是用于指定模型字段作為主鍵的屬性選項。
主鍵是數(shù)據(jù)庫表中的一種特殊字段,它用于唯一標識表中的每一行記錄。主鍵字段的值在整個表中必須是唯一的,并且不能為空。通過將 primaryKey 設(shè)置為 true,可以指示 Sequelize 將該字段設(shè)置為模型的主鍵。
autoIncrement:自增字段
autoIncrement 是一個用于指定模型字段是否為自增字段的屬性選項。
自增字段是一種特殊類型的主鍵,它的值會在每次插入新記錄時自動遞增。通常用于為每個新記錄分配唯一的標識符。自增字段的常見類型為整數(shù)(例如,INTEGER)。通過將 autoIncrement 設(shè)置為 true,可以指示 Sequelize 將該字段設(shè)置為自增字段。
使用自增字段可以方便地生成唯一的標識符,而無需顯式指定每個新記錄的值。數(shù)據(jù)庫在插入新記錄時會自動遞增該字段的值。這對于需要快速添加新記錄并確保主鍵唯一性的情況非常有用。
注意,autoIncrement 屬性僅對整數(shù)類型的字段有效。
unique:是否唯一
unique 用于定義模型字段是否唯一的屬性選項。
當將 unique 設(shè)置為 true 時,表示該字段的值必須在整個表中是唯一的。也就是說,在同一列中,每個記錄都必須有一個唯一的值,不能重復(fù)。
validate:校驗規(guī)則
validate 是用于定義模型字段驗證規(guī)則的屬性選項。
通過 validate 屬性,可以定義一個包含驗證規(guī)則的對象,用于驗證模型字段的值是否符合指定的條件。validate 屬性可以包含多個驗證規(guī)則,每個規(guī)則可以是一個函數(shù)或一個對象。下面是一些常見的驗證規(guī)則屬性值:
- notEmpty:確保字段的值不為空。
- len:檢查字段的長度是否在指定范圍內(nèi)??梢栽O(shè)置一個數(shù)組,如 [min, max]。
- isEmail:驗證字段的值是否為有效的電子郵件地址。
- isUrl:驗證字段的值是否為有效的 URL。
- isAlpha:驗證字段的值是否只包含字母字符。
- isAlphanumeric:驗證字段的值是否只包含字母和數(shù)字字符。
- isNumeric:驗證字段的值是否為數(shù)字。
- isInt:驗證字段的值是否為整數(shù)。
- isFloat:驗證字段的值是否為浮點數(shù)。
- isDate:驗證字段的值是否為有效的日期。
- isAfter:驗證字段的值是否在指定日期之后。
- isBefore:驗證字段的值是否在指定日期之前。
- isIn:驗證字段的值是否在指定的數(shù)組中。
這只是一些常見的驗證規(guī)則,Sequelize 還提供了更多的內(nèi)置驗證規(guī)則。此外,你還可以定義自定義的驗證函數(shù)來進行復(fù)雜的驗證邏輯。
const User = sequelize.define('User', {
username: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true,
len: [3, 20],
isAlphanumeric: true,
},
},
email: {
type: Sequelize.STRING,
allowNull: false,
validate: {
isEmail: true,
},
},
});
comment:注釋
comment 是用于為模型字段添加注釋的屬性選項。
注釋是對字段的描述性文本,可以提供關(guān)于字段用途、含義或其他相關(guān)信息的補充說明。注釋對于理解和維護數(shù)據(jù)庫結(jié)構(gòu)非常有幫助。
const User = sequelize.define('User', {
username: {
type: Sequelize.STRING,
comment: '用戶的用戶名', // 字段注釋
},
email: {
type: Sequelize.STRING,
comment: '用戶的電子郵件地址', // 字段注釋
},
});
field:字段重命名
field 是一個用于指定模型字段在數(shù)據(jù)庫中的實際名稱的屬性選項。
默認情況下,Sequelize 會將模型定義中的字段名稱直接映射到數(shù)據(jù)庫表中對應(yīng)的列名。但是,有時可能希望在數(shù)據(jù)庫中使用不同的列名,這時可以使用 field 屬性來指定實際的數(shù)據(jù)庫列名。
const User = sequelize.define('User', {
firstName: {
type: Sequelize.STRING,
field: 'first_name', // 指定數(shù)據(jù)庫對應(yīng)的列名
},
lastName: {
type: Sequelize.STRING,
field: 'last_name', // 指定數(shù)據(jù)庫對應(yīng)的列名
},
});
在上述示例中,firstName 字段的 field 屬性設(shè)置為 first_name,lastName 字段的 field 屬性設(shè)置為 last_name。這將導(dǎo)致在數(shù)據(jù)庫表中創(chuàng)建名為 first_name和last_name 的列。
使用 field 屬性可以非常靈活地控制模型字段與數(shù)據(jù)庫列的映射關(guān)系。這在需要與遺留數(shù)據(jù)庫或特定數(shù)據(jù)庫命名約定交互的情況下非常有用。
注意,如果不指定 field 屬性,Sequelize 將默認使用與模型字段名稱相同的列名。
get 和 set:字段值計算
get
get 字段表示一個自定義的 getter 方法。它是一個通過訪問模型實例屬性來獲取計算值的函數(shù)。
使用 get 字段,可以定義一個自定義的 getter 方法,該方法會在訪問特定屬性時被調(diào)用,以便根據(jù)需要對屬性進行計算、處理或轉(zhuǎn)換。
const User = sequelize.define('User', {
firstName: {
type: Sequelize.STRING,
allowNull: false,
},
lastName: {
type: Sequelize.STRING,
allowNull: false,
},
fullName: {
type: Sequelize.VIRTUAL, // 虛擬屬性
get() {
return `${this.firstName} ${this.lastName}`;
},
},
});
const user = User.build({
firstName: 'Alice',
lastName: 'Smith',
});
console.log(user.fullName); // 輸出:Alice Smith
使用 get 字段可以方便地在訪問模型屬性時進行額外的計算或處理。它使得模型實例的屬性具有更多的靈活性和復(fù)雜性。
set
set 字段表示一個自定義的 setter 方法。它允許你在設(shè)置屬性值時執(zhí)行一些自定義邏輯或轉(zhuǎn)換。
使用 set 字段,可以定義一個自定義的 setter 方法,該方法會在設(shè)置特定屬性的值時被調(diào)用,以便對該值進行處理、驗證或轉(zhuǎn)換。
const User = sequelize.define('User', {
fullName: {
type: Sequelize.STRING,
set(value) {
const names = value.split(' ');
this.setDataValue('firstName', names[0]);
this.setDataValue('lastName', names[1]);
},
},
});
const user = User.build();
user.fullName = 'Alice Smith';
console.log(user.firstName); // 輸出:Alice
console.log(user.lastName); // 輸出:Smith
當給 user.fullName 賦值時,Sequelize 將自動調(diào)用定義的 setter 方法,并進行相應(yīng)的屬性設(shè)置。
使用 set 字段可以方便地在設(shè)置模型屬性值時執(zhí)行自定義的邏輯或轉(zhuǎn)換操作。它使得模型屬性的賦值具有更多的靈活性和復(fù)雜性。
references:模型關(guān)聯(lián)
references 是一個模型定義中的選項,用于指定關(guān)聯(lián)關(guān)系中引用的目標模型和目標屬性。
當在 Sequelize 模型定義中使用 references 選項,它表示當前模型與另一個模型之間的關(guān)聯(lián)關(guān)系,并指定了相關(guān)聯(lián)的目標模型和目標屬性。
const User = sequelize.define('User', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: Sequelize.STRING,
allowNull: false,
},
});
const Post = sequelize.define('Post', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
title: {
type: Sequelize.STRING,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
references: {
model: User, // 引用的目標模型
key: 'id', // 引用的目標屬性
},
},
});
這里定義了兩個模型:User 和 Post。在 Post 模型的定義中,使用了 references 選項來創(chuàng)建一個與 User 模型的關(guān)聯(lián)關(guān)系。
references 選項包含兩個屬性:
- model:指定關(guān)聯(lián)的目標模型,這里是 User。
- key:指定關(guān)聯(lián)的目標屬性,這里是 id。
這意味著 Post 模型中的 userId 屬性將引用 User 模型中的 id 屬性作為關(guān)聯(lián)。這意味著 userId 和 User 模型的 id 屬性具有相同的值。
通過使用 references 選項,Sequelize 可以根據(jù)關(guān)聯(lián)關(guān)系設(shè)置合適的數(shù)據(jù)庫約束,并幫助你在查詢中輕松處理模型之間的關(guān)聯(lián)。
onDelete:刪除關(guān)聯(lián)
onDelete 是一個定義關(guān)聯(lián)關(guān)系時可以設(shè)置的選項之一。它用于指定當關(guān)聯(lián)模型的記錄被刪除時要執(zhí)行的操作。
使用 onDelete 選項,可以定義在刪除關(guān)聯(lián)模型的記錄時應(yīng)該執(zhí)行的操作,例如級聯(lián)刪除、設(shè)置為 null 或什么都不做等。
以下是一些常用的 onDelete 選項值及其含義:
- CASCADE:級聯(lián)刪除。當關(guān)聯(lián)模型的記錄被刪除時,與之關(guān)聯(lián)的記錄也將被刪除。
- SET NULL:設(shè)置為 null。當關(guān)聯(lián)模型的記錄被刪除時,與之關(guān)聯(lián)的記錄的外鍵值將被設(shè)置為 null。
- SET DEFAULT:設(shè)置為默認值。當關(guān)聯(lián)模型的記錄被刪除時,與之關(guān)聯(lián)的記錄的外鍵值將被設(shè)置為默認值。
- RESTRICT:限制。當關(guān)聯(lián)模型的記錄被刪除時,如果還有與之關(guān)聯(lián)的記錄存在,則會阻止刪除操作。
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
}
});
const Post = sequelize.define('Post', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
},
userId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
},
onDelete: 'CASCADE' // 當關(guān)聯(lián)的 User 記錄被刪除時,與之關(guān)聯(lián)的 Post 記錄也將被刪除
}
});
這里定義了一個 User 模型和一個 Post 模型。在 Post 模型的定義中,我們設(shè)置了與 User 模型的關(guān)聯(lián),并在 userId 屬性上使用了 onDelete: 'CASCADE' 選項。這意味著當與之關(guān)聯(lián)的 User 記錄被刪除時,與之關(guān)聯(lián)的 Post 記錄也將被級聯(lián)刪除。
onUpdate:更新關(guān)聯(lián)
onUpdate 是一個定義關(guān)聯(lián)關(guān)系時可以設(shè)置的選項之一。它用于指定當關(guān)聯(lián)模型的記錄被更新時要執(zhí)行的操作。
使用 onUpdate 選項,可以定義在更新關(guān)聯(lián)模型的記錄時應(yīng)該執(zhí)行的操作,例如級聯(lián)更新或什么都不做等。
以下是一些常用的 onUpdate 選項值及其含義:
- CASCADE:級聯(lián)更新。當關(guān)聯(lián)模型的記錄被更新時,與之關(guān)聯(lián)的記錄也將相應(yīng)地進行更新。
- SET NULL:設(shè)置為 null。當關(guān)聯(lián)模型的記錄被更新時,與之關(guān)聯(lián)的記錄的外鍵值將被設(shè)置為 null。
- SET DEFAULT:設(shè)置為默認值。當關(guān)聯(lián)模型的記錄被更新時,與之關(guān)聯(lián)的記錄的外鍵值將被設(shè)置為默認值。
- RESTRICT:限制。當關(guān)聯(lián)模型的記錄被更新時,如果有其他關(guān)聯(lián)記錄存在,則會阻止更新操作。
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
}
});
const Post = sequelize.define('Post', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
},
userId: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'id'
},
onUpdate: 'CASCADE' // 當關(guān)聯(lián)的 User 記錄被更新時,與之關(guān)聯(lián)的 Post 記錄也將被相應(yīng)地更新
}
});
這里定義了一個 User 模型和一個 Post 模型。在 Post 模型的定義中,我們設(shè)置了與 User 模型的關(guān)聯(lián),并在 userId 屬性上使用了 onUpdate: 'CASCADE' 選項。這意味著當與之關(guān)聯(lián)的 User 記錄被更新時,與之關(guān)聯(lián)的 Post 記錄也將相應(yīng)地進行級聯(lián)更新。
模型繼承
模型繼承是一種將一個模型繼承自另一個模型的機制。這使得你可以從一個已有的模型中派生出新的模型,并繼承它的屬性、方法和關(guān)聯(lián)關(guān)系,從而實現(xiàn)代碼重用和模型的層次結(jié)構(gòu)組織。
模型繼承通過使用 sequelize.define() 方法的 options 參數(shù)來實現(xiàn)。在定義模型時,可以指定 options 參數(shù)中的 extend 屬性,來指定該模型繼承自哪個父模型。被繼承的父模型稱為基礎(chǔ)(或父)模型,而繼承的新模型稱為派生(或子)模型。
下面來看看如何在 Sequelize 中進行模型繼承:
const { Model, DataTypes } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password');
// 定義基礎(chǔ)模型
const BaseModel = sequelize.define('base', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
// 其他屬性...
});
// 定義派生模型,并繼承基礎(chǔ)模型
const DerivedModel = sequelize.define('derived', {
age: {
type: DataTypes.INTEGER,
allowNull: false,
},
// 其他屬性...
}, {
extend: BaseModel,
});
// 創(chuàng)建派生模型的實例
DerivedModel.create({ name: 'John', age: 25 })
.then((instance) => {
console.log(instance.toJSON());
})
.catch(console.error);
這里首先定義了一個基礎(chǔ)模型 BaseModel,它有一個名為 name 的屬性。然后,定義了派生模型 DerivedModel,它繼承自基礎(chǔ)模型,并新增了一個名為 age 的屬性。最后,我們使用派生模型的 create() 方法創(chuàng)建一個新的實例,并輸出其序列化后的 JSON 數(shù)據(jù)。
通過模型繼承,可以在派生模型中重用和擴展基礎(chǔ)模型的屬性、方法和關(guān)聯(lián)關(guān)系,從而簡化代碼的編寫和維護。這對于構(gòu)建具有層次結(jié)構(gòu)的數(shù)據(jù)模型非常有用,例如用戶、管理員和超級管理員之間的繼承關(guān)系。
修改模型
在 Sequelize 中,修改、刪除已有字段或新增字段的過程如下:
- 在模型定義中進行相應(yīng)的更改。
- 使用 Sequelize 提供的遷移工具執(zhí)行數(shù)據(jù)庫遷移操作。
過程如下:
- 修改已有字段的數(shù)據(jù)類型和屬性:
// 修改已有字段的數(shù)據(jù)類型和屬性
await sequelize.queryInterface.changeColumn('User', 'age', {
type: Sequelize.STRING,
allowNull: true,
});
- 刪除已有字段:
// 刪除已有字段
await sequelize.queryInterface.removeColumn('User', 'age');
- 新增字段:
{
// 新增字段
await sequelize.queryInterface.addColumn('User', 'gender', {
type: Sequelize.STRING,
allowNull: true,
});
這里用 Sequelize 提供的 queryInterface 對象來執(zhí)行數(shù)據(jù)庫遷移操作。該對象提供了一系列方法來修改表結(jié)構(gòu)。
- 對于修改已有字段,可以使用 changeColumn 方法指定要更改的模型名稱、字段名稱和新的屬性。
- 對于刪除已有字段,可以使用 removeColumn 方法指定要刪除的模型名稱和字段名稱。
- 對于新增字段,我們可以使用 addColumn 方法指定要新增字段的模型名稱、字段名稱和屬性。
在 Sequelize 中,修改模型定義并執(zhí)行相應(yīng)的遷移操作后,默認情況下數(shù)據(jù)庫表不會自動同步更改。你需要顯式地調(diào)用 sequelize.sync 方法來同步模型和數(shù)據(jù)庫表。以下是一個在執(zhí)行遷移操作后手動調(diào)用 sequelize.sync 方法的示例代碼:
// 執(zhí)行遷移操作...
// ...
// 手動同步模型和數(shù)據(jù)庫表
await sequelize.sync();
這里使用 await sequelize.sync() 方法手動同步模型和數(shù)據(jù)庫表。這將更新數(shù)據(jù)庫表結(jié)構(gòu)以匹配模型定義的更改。
注意,sequelize.sync() 方法會根據(jù)模型定義生成創(chuàng)建、修改或刪除表的 SQL 命令,然后將其應(yīng)用于數(shù)據(jù)庫。因此,請確保在生產(chǎn)環(huán)境中謹慎使用該方法,并提前備份重要的數(shù)據(jù)。
如果使用 Sequelize-CLI 或其他遷移工具來管理數(shù)據(jù)庫遷移,它們通常會自動處理模型與數(shù)據(jù)庫表的同步操作,你不需要手動調(diào)用 sequelize.sync() 方法。但如果你手動修改了模型定義或直接使用 queryInterface 修改數(shù)據(jù)庫表結(jié)構(gòu),則需要手動同步模型和數(shù)據(jù)庫表。
刪除模型
要刪除 Sequelize 中的模型,可以使用 sequelize.drop 方法。
以下是一個示例代碼來刪除一個名為 User 的模型:
// 刪除模型
await User.drop();
注意,刪除模型將會永久刪除數(shù)據(jù)庫表,包括其中的數(shù)據(jù)。在執(zhí)行模型刪除操作之前,請確保備份重要的數(shù)據(jù)。請謹慎操作刪除模型,確保你的操作不會導(dǎo)致數(shù)據(jù)丟失或不可逆的更改。
在異步函數(shù)中執(zhí)行刪除操作,并在完成后輸出相應(yīng)的信息。最后,記得關(guān)閉 Sequelize 連接,以避免資源泄漏。
模型查詢
先來看看查詢是一些通用查詢參數(shù)。
通用參數(shù)
where:查詢條件
使用 where 方法可以添加查詢條件,它可以用于查詢語句中的各種不同部分,如 findOne 和 findAll 等。通過 where 方法可以根據(jù)指定的條件過濾數(shù)據(jù)庫中的記錄。
Op 對象是 Sequelize 中用于定義各種操作符的對象。它提供了很多常用的操作符,可以在查詢條件中使用。以下是一些常見的 Op 屬性及其對應(yīng)的操作符:
- Op.eq:等于
- Op.ne:不等于
- Op.gt:大于
- Op.gte:大于等于
- Op.lt:小于
- Op.lte:小于等于
- Op.like:模糊匹配
- Op.notLike:不匹配
- Op.iLike:忽略大小寫的模糊匹配
- Op.notILike:忽略大小寫的不匹配
- Op.in:在給定數(shù)組中的值
- Op.notIn:不在給定數(shù)組中的值
- Op.between:在給定范圍內(nèi)的值
- Op.notBetween:不在給定范圍內(nèi)的值
等于
model.findAll({
where: {
age: 18
}
});
上述代碼會查找 age 等于 18 的所有記錄。
不等于
model.findAll({
where: {
age: {[Op.ne]: 18}
}
});
上述代碼會查找 age 不等于 18 的所有記錄。
大于
model.findAll({
where: {
age: {[Op.gt]: 18}
}
});
上述代碼會查找 age 大于 18 的所有記錄。
小于
model.findAll({
where: {
age: {[Op.lt]: 18}
}
});
上述代碼會查找 age 小于 18 的所有記錄。
大于等于
model.findAll({
where: {
age: {[Op.gte]: 18}
}
});
上述代碼會查找 age 大于等于 18 的所有記錄。
小于等于
model.findAll({
where: {
age: {[Op.lte]: 18}
}
});
上述代碼會查找 age 小于等于 18 的所有記錄。
模糊匹配
model.findAll({
where: {
name: {
[Op.like]: '%John%'
}
}
});
上述代碼會查找 name 字段中包含 "John" 的所有記錄。
也可以使用 $like 來查詢,這是 sequelize 的舊語法,建議使用新語法 [Op.like] 來查詢:
model.findAll({
where: {
name: {
$like: '%John%'
}
}
});
范圍
model.findAll({
where: {
age: {[Op.between]: [18, 30]}
}
});
上述代碼會查找 age 在 18 到 30 之間的所有記錄。
子查詢
可以使用 [Op.or] 操作符來實現(xiàn)查詢一個字段等于 a 或 b 的操作。
const { Op } = require('sequelize');
const users = await User.findAll({
where: {
[Op.or]: [
{ name: 'a' },
{ name: 'b' },
],
},
});
這里使用 findAll 方法查找所有名字等于 'a' 或 'b' 的用戶。其中,[Op.or] 表示 OR 連接操作符,將兩個條件拼接成 OR 條件。
注意,在實際使用時,如果需要查詢多個可能值,可以使用[Op.in]操作符,例如:
const users = await User.findAll({
where: {
name: {
[Op.in]: ['a', 'b'],
},
},
});
上述代碼將會查詢所有名字等于 'a' 或 'b' 的用戶。
include:包含關(guān)聯(lián)模型
在 Sequelize 中,可以使用關(guān)聯(lián)來定義模型之間的關(guān)系,例如一對一、一對多或多對多關(guān)系。當查詢模型時,如果希望返回與該模型關(guān)聯(lián)的其他模型的屬性,就需要使用 include 選項來包含關(guān)聯(lián)模型。可以根據(jù)需要輕松地從其他模型中獲取相關(guān)數(shù)據(jù),而無需單獨進行額外的查詢操作。
User.findAll({
include: {
model: Post,
attributes: ['title', 'content']
}
})
.then((users) => {
// 處理查詢結(jié)果
users.forEach((user) => {
console.log('用戶名:', user.name);
console.log('用戶發(fā)布的文章:');
user.Posts.forEach((post) => {
console.log('標題:', post.title);
console.log('內(nèi)容:', post.content);
});
});
})
.catch((error) => {
// 處理查詢錯誤
});
這里使用 User 模型進行查詢,通過 include 選項包含了關(guān)聯(lián)的 Post 模型。然后,在 .then 回調(diào)函數(shù)中處理查詢結(jié)果。每個用戶對象都包含了他們的相關(guān)文章數(shù)據(jù),可以通過訪問 user.Posts 屬性來獲取關(guān)聯(lián)的文章數(shù)據(jù)。
當在主模型上執(zhí)行查詢后,包含關(guān)聯(lián)模型的查詢實際上是在主模型查詢的基礎(chǔ)上進行的。
首先,使用主模型進行查詢,獲取與查詢條件匹配的主模型數(shù)據(jù)。然后,在查詢結(jié)果中包含的每個主模型實例上,Sequelize 將自動執(zhí)行額外的查詢來獲取與之關(guān)聯(lián)的其他模型的數(shù)據(jù)。
這種查詢方式稱為延遲加載或延遲關(guān)聯(lián)。它的優(yōu)點是只有在需要訪問關(guān)聯(lián)模型數(shù)據(jù)時才執(zhí)行額外的查詢,避免了不必要的查詢開銷。
在上面的示例中,當調(diào)用 User.findAll() 查詢用戶時,Sequelize 會從數(shù)據(jù)庫獲取與查詢條件匹配的用戶數(shù)據(jù)。然后,當訪問 user.Posts 屬性時,Sequelize 會自動執(zhí)行另一個查詢來獲取該用戶關(guān)聯(lián)的文章數(shù)據(jù)。
在查詢時包含多個關(guān)聯(lián)模型,可以通過 Sequelize 的 include 選項的不同方式來實現(xiàn)。下面有兩種常用的方法:
- 使用數(shù)組形式包含多個關(guān)聯(lián)模型:
User.findAll({
include: [
{ model: Profile },
{ model: Post }
]
})
.then((users) => {
// 處理查詢結(jié)果
users.forEach((user) => {
console.log('用戶名:', user.name);
console.log('用戶配置:', user.Profile);
console.log('用戶文章:', user.Posts);
});
})
.catch((error) => {
// 處理查詢錯誤
});
在上述代碼中,將要包含的關(guān)聯(lián)模型作為對象放入數(shù)組中,并將該數(shù)組作為 include 選項的值。這樣,在查詢結(jié)果中就會包含多個關(guān)聯(lián)模型的數(shù)據(jù)。
- 嵌套方式包含多個關(guān)聯(lián)模型:
User.findAll({
include: [
{
model: Profile,
include: [Category] // 在 Profile 模型中嵌套包含 Category 模型
},
{ model: Post }
]
})
.then((users) => {
// 處理查詢結(jié)果
users.forEach((user) => {
console.log('用戶名:', user.name);
console.log('用戶配置:', user.Profile);
console.log('用戶文章:', user.Posts);
console.log('用戶配置的類別:', user.Profile.Category);
});
})
.catch((error) => {
// 處理查詢錯誤
});
這里使用嵌套的方式,在其中一個關(guān)聯(lián)模型的 include 選項中,再嵌套包含另一個關(guān)聯(lián)模型。這樣可以實現(xiàn)更深層次的關(guān)聯(lián)查詢。
通過以上方式,可以在查詢時包含多個關(guān)聯(lián)模型,并獲取它們的數(shù)據(jù)。根據(jù)需求和模型之間的關(guān)系,可以靈活地組合和嵌套使用 include 選項來包含多個關(guān)聯(lián)模型。
注意:只有在模型定義中定義了關(guān)聯(lián)關(guān)系,才能在查詢時包含關(guān)聯(lián)模型。
attributes:返回字段
可以使用 attributes 選項指定要返回的字段。示例:attributes: ['id', 'name']。它用于控制查詢結(jié)果中包含哪些屬性或排除哪些屬性,可以接受多種形式的參數(shù),以控制返回的屬性。
以下是幾種常見的 attributes 選項的用法:
- 字符串數(shù)組:可以傳入一個字符串數(shù)組,表示要返回的屬性名。示例:attributes: ['name', 'age'],表示查詢結(jié)果將僅包含 'name' 和 'age' 兩個字段。
- 嵌套對象:可以傳入一個嵌套對象,用于更復(fù)雜的字段控制。示例:attributes: { include: ['name'], exclude: ['age'] },表示查詢結(jié)果將包含 name 字段,并排除 age 字段。
- 聚合函數(shù):可以使用聚合函數(shù)對屬性進行計算,并將計算結(jié)果命名為新的屬性。示例:attributes: [[sequelize.fn('SUM', sequelize.col('quantity')), 'totalQuantity']],表示查詢結(jié)果中將返回一個計算總和的聚合函數(shù),并將計算結(jié)果命名為totalQuantity。
注意事項:
- 如果不指定 attributes 選項,默認情況下會返回所有模型的屬性;指定了 attributes 選項后,只會返回指定的屬性。
- 使用 attributes 選項時,如果要返回關(guān)聯(lián)模型的屬性,需要在關(guān)聯(lián)模型上設(shè)置 include 選項。
order:排序規(guī)則
可以使用 order 選項來指定返回結(jié)果的排序規(guī)則。示例:order: [['createdAt', 'DESC']],它表示按照 createdAt 字段進行降序排列。
在 Sequelize 中,可以通過 order 選項來指定查詢結(jié)果的排序規(guī)則。排序規(guī)則由一個二維數(shù)組表示,每個子數(shù)組包含兩個元素:排序字段和排序方式。排序字段可以是模型的屬性名或關(guān)聯(lián)模型的屬性名。排序方式可以是 'ASC'(升序)或 'DESC'(降序)。
以下是order 選項常見的用法:
- 單字段排序:可以只指定一個排序字段和排序方式。示例:order: [['fieldName', 'ASC']]。
- 多字段排序:可以指定多個排序字段和排序方式,按照指定的順序依次排序。示例:order: [['field1', 'ASC'], ['field2', 'DESC']]。
- 關(guān)聯(lián)模型排序:可以使用關(guān)聯(lián)模型的屬性進行排序。示例:order: [['RelatedModel', 'fieldName', 'ASC']]。
注意事項:
- 排序字段必須是模型或關(guān)聯(lián)模型的屬性名。
- 排序方式應(yīng)為 'ASC' 或 'DESC'。
- 在查詢語句中使用多個排序條件時,將按照指定的順序依次應(yīng)用這些條件。
Model.findOne({
where: {
// 查詢條件
status: 'active'
},
order: [['createdAt', 'DESC']]
})
.then((records) => {
// 處理查詢結(jié)果
})
.catch((error) => {
// 處理查詢錯誤
})
這里使用了 order 選項,通過 [['createdAt', 'DESC']] 指定了按照 createdAt 字段進行降序排列。
limit:查詢結(jié)果的數(shù)量
用于限制查詢結(jié)果返回的記錄數(shù)量,常用于分頁查詢。
Model.findAll({
limit: 10 // 返回最多 10 條記錄
})
.then((results) => {
// 處理查詢結(jié)果
})
.catch((error) => {
// 處理查詢錯誤
});
offset:查詢結(jié)果的偏移量
用于設(shè)置查詢結(jié)果的偏移量,從指定位置開始返回結(jié)果,常用于分頁查詢。這個偏移量是基于索引的,而索引是從零開始計數(shù)的。
Model.findAll({
offset: 5 // 忽略前 5 條記錄
})
.then((results) => {
// 處理查詢結(jié)果
})
.catch((error) => {
// 處理查詢錯誤
});
group:結(jié)果分組
用于對結(jié)果進行分組:按照指定的字段值進行分類歸納,將具有相同字段值的記錄放在一組中。
Model.findAll({
attributes: ['age'],
group: ['age']
})
.then((results) => {
// 處理查詢結(jié)果
results.forEach((group) => {
console.log('分組:');
group.forEach((record) => {
console.log('記錄:', record);
});
});
})
.catch((error) => {
// 處理查詢錯誤
});
這里使用 group 選項對 age 字段進行分組。查詢結(jié)果 results 是一個數(shù)組,其中每個元素代表一個分組。對于每個分組,可以遍歷內(nèi)層數(shù)組 group,其中的每個元素代表該分組中的一條記錄。
distinct:結(jié)果去重
當設(shè)置 distinct: true 時,查詢結(jié)果將會返回去重后的記錄。這在某些情況下非常有用,例如獲取一個字段的唯一值列表或者按照某個字段進行分組統(tǒng)計時。
這里使用 distinct: true 設(shè)置查詢結(jié)果為去重模式,并指定了要查詢的字段為 name。查詢結(jié)果將只包含去重后的姓名列表。
例如,假設(shè)有一個名為 User 的模型,并且希望獲取所有不重復(fù)的用戶名:
const users = await User.findAll({
attributes: ['name'],
distinct: true
});
這里通過設(shè)置 distinct: true 來確保只返回不重復(fù)的用戶名。查詢結(jié)果將只包含唯一的、不重復(fù)的用戶名。
注意,distinct 選項必須與指定的查詢字段一起使用,確保只對指定的字段進行去重操作。
findOne:查詢第一條
查詢符合條件的第一條記錄。
Model.findOne({
where: {
// 查詢條件
id: 1
}
})
.then((record) => {
if (record) {
console.log('查詢到的記錄:', record.get({ plain: true }));
} else {
console.log('未找到符合條件的記錄');
}
})
.catch((error) => {
// 處理查詢錯誤
});
這個方法的返回值是一個 Sequelize Model 對象,其中包含與記錄相關(guān)聯(lián)的屬性、方法和關(guān)系。它具有以下特性:
- 屬性訪問:可以通過屬性名直接訪問記錄的字段值,例如 record.fieldName。
- 數(shù)據(jù)獲?。嚎梢允褂?nbsp;.get() 方法獲取包含所有字段的對象形式的記錄數(shù)據(jù),例如 record.get(),其用法如下。
record.get():返回一個包含所有字段的對象,其中字段名作為鍵,字段值作為值。這個對象是 Sequelize 模型實例,包含與記錄相關(guān)聯(lián)的屬性和方法。
record.get({ plain: true }):返回一個純對象,只包含記錄的原始字段和值,不包含與 Sequelize 相關(guān)的屬性和方法。
獲取指定字段的值:可以傳遞一個或多個字段名作為參數(shù),獲取特定字段的值。示例:record.get('fieldName') 或 record.get('field1', 'field2')。
排除指定字段:可以使用 { exclude: ['fieldName'] } 選項來排除指定的字段,獲取除這些字段外的其他字段。示例:record.get({ exclude: ['fieldName'] })。
只獲取指定字段:可以使用 { attributes: ['fieldName'] } 選項來只獲取指定的字段。示例:record.get({ attributes: ['fieldName'] })。
Model.findOne({
where: {
// 查詢條件
id: 1
}
})
.then((record) => {
if (record) {
const fieldValue = record.get('fieldName');
console.log('字段值:', fieldValue);
const excludedData = record.get({ exclude: ['field1', 'field2'] });
console.log('排除字段后的數(shù)據(jù):', excludedData);
const selectedData = record.get({ attributes: ['field1', 'field2'] });
console.log('只包含指定字段的數(shù)據(jù):', selectedData);
} else {
console.log('未找到符合條件的記錄');
}
})
.catch((error) => {
// 處理查詢錯誤
});
注意,Model.findOne 方法只返回滿足查詢條件的第一條記錄。如果沒有符合條件的記錄,則返回 null。
另外,distinct: true 在某些數(shù)據(jù)庫管理系統(tǒng)中可能會導(dǎo)致性能下降,因為它需要進行更多的計算來實現(xiàn)去重。所以在使用 distinct: true 時,要謹慎考慮其對性能的影響。
findAll:查詢?nèi)?/h3>
sequelize.findAll() 用于從數(shù)據(jù)庫中檢索所有匹配給定條件的記錄。它的語法如下:
Model.findAll({
attributes: [], // 要選擇的屬性列表,默認為所有屬性
where: {}, // 過濾條件
include: [], // 關(guān)聯(lián)模型
order: [], // 排序規(guī)則
limit: 0, // 返回的最大記錄數(shù),默認為0(返回所有記錄)
offset: 0, // 結(jié)果集的起始偏移量,默認為0
});
參數(shù)說明:
- attributes:指定要選擇的屬性列表,如果為空,則返回所有屬性。
- where:指定過濾條件,可以使用各種條件運算符(如等于、不等于、大于、小于等)來篩選記錄。
- include:指定要關(guān)聯(lián)的其他模型,可以進行關(guān)聯(lián)查詢。
- order:指定結(jié)果集的排序規(guī)則。
- limit:指定要返回的最大記錄數(shù),默認為0,表示返回所有符合條件的記錄。
- offset:指定結(jié)果集的起始偏移量,默認為0。
這個方法將返回一個Promise,當查詢成功時,Promise將解析為包含所有符合條件的記錄的數(shù)組。以下是一個示例:
Model.findAll({
where: {
// 查詢條件
status: 'active'
}
})
.then((records) => {
if (records.length > 0) {
console.log('查詢到的記錄數(shù):', records.length);
records.forEach((record) => {
const data = record.get();
console.log('記錄數(shù)據(jù):', data);
});
} else {
console.log('未找到符合條件的記錄');
}
})
.catch((error) => {
// 處理查詢錯誤
});
注意,如果沒有查詢到符合條件的記錄,返回的數(shù)組將為空。
findByPk:根據(jù)主鍵值查詢
根據(jù)主鍵值查詢記錄,它的語法如下:
Model.findByPk(id, options);
參數(shù)說明:
- id:要查詢的記錄的主鍵值。
- options:可選參數(shù),用于指定進一步的配置,比如關(guān)聯(lián)模型等。
下面來看一個例子,通過主鍵值來獲取特定的用戶記錄:
const user = await User.findByPk(1);
console.log(user);
上述代碼將查詢主鍵值為 1 的用戶記錄,并將結(jié)果保存在 user 變量中。如果找到匹配的記錄,則 user 將是一個包含該記錄的對象。否則,user 將是 null。
如果要通過主鍵值獲取多個記錄,可以傳入一個數(shù)組作為 id 參數(shù),如:
const users = await User.findByPk([1, 2, 3]);
console.log(users);
上述代碼將查詢主鍵值為 1、2 和 3 的用戶記錄,并將結(jié)果保存在 users 變量中,它將是一個包含這些記錄的數(shù)組。
findByPk 也可以與其他查詢配置選項一起使用,例如關(guān)聯(lián)模型、選擇屬性等??梢栽?nbsp;options 參數(shù)中指定這些額外的配置選項。
注意:findByPk 方法返回一個 Promise,在查詢成功時解析為匹配的記錄(或記錄數(shù)組),在查詢失敗時拒絕為錯誤對象。因此,需要使用 await 或 .then() 來處理查詢結(jié)果或捕獲錯誤。
在 Sequelize 中,主鍵值是指用于唯一標識數(shù)據(jù)庫表中每個記錄的列或?qū)傩?。主鍵值在表中具有唯一性,沒有重復(fù)的值,且不能為空。在 Sequelize 模型定義中,可以通過 primaryKey: true 來將某個屬性指定為主鍵。例如:
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: DataTypes.STRING,
email: DataTypes.STRING
});
在上述例子中,id 屬性被指定為主鍵。它的類型為整數(shù)(INTEGER),并且設(shè)置了 primaryKey: true 表示該屬性是主鍵。此外,還可以使用 autoIncrement: true 來指定該主鍵自動增長,以便在插入新記錄時自動生成唯一的主鍵值。
當使用 findByPk、update、destroy 等方法時,通常會使用主鍵值來準確定位要操作的記錄。通過提供正確的主鍵值,Sequelize 可以根據(jù)主鍵來查詢、更新或刪除相應(yīng)的記錄。
findOrCreate:查詢或創(chuàng)建
findOrCreate 用于根據(jù)指定條件查找數(shù)據(jù)庫中的記錄,如果找到匹配的記錄,則返回該記錄;如果找不到匹配的記錄,則創(chuàng)建一個新的記錄并返回。它的語法如下:
Model.findOrCreate({
where: { ... },
defaults: { ... },
...
});
參數(shù)說明:
- where:包含查找條件的對象,用于指定要匹配的屬性和值。
- defaults:包含要創(chuàng)建新記錄時的默認值的對象。
- ...:其他可選參數(shù),用于進一步配置查詢。
使用 findOrCreate 方法時,Sequelize 首先根據(jù) where 條件嘗試在數(shù)據(jù)庫中查找符合條件的記錄。如果找到匹配的記錄,則返回該記錄作為結(jié)果。
如果沒有找到匹配的記錄,則使用 defaults 指定的默認值創(chuàng)建一個新的記錄,并返回該新記錄作為結(jié)果。默認值將應(yīng)用于新創(chuàng)建的記錄的屬性。
例如,假設(shè)有一個名為 User 的模型表示用戶表,其中 email 是唯一的:
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true
}
});
現(xiàn)在想根據(jù)郵箱查找用戶記錄,如果找到則返回該記錄,如果找不到則創(chuàng)建一個新用戶記錄??梢允褂?nbsp;findOrCreate 方法:
const [user, created] = await User.findOrCreate({
where: { email: 'example@example.com' },
defaults: { name: 'John Doe' }
});
console.log(user); // 匹配的記錄或新創(chuàng)建的記錄
console.log(created); // 表示是否新創(chuàng)建了記錄的布爾值
上述代碼將根據(jù)指定的郵箱查找用戶記錄,如果找到匹配的記錄,則返回該記錄。如果沒有找到匹配的記錄,則創(chuàng)建一個新的記錄,并返回新創(chuàng)建的記錄。
findOrCreate 方法返回一個包含兩個元素的數(shù)組:第一個元素是匹配的記錄(已存在或新創(chuàng)建),第二個元素是一個布爾值,表示是否新創(chuàng)建了記錄。
如果有多個符合條件的記錄,findOrCreate 方法僅返回匹配的第一個記錄。它不會返回所有符合條件的記錄。
findAndCountAll:查詢記錄和數(shù)量
findAndCountAll 用于查找滿足指定條件的所有記錄,并返回滿足條件的記錄數(shù)組和記錄總數(shù)。它的語法如下:
Model.findAndCountAll({
where: { ... },
include: [ ... ],
offset: ...,
limit: ...,
order: [...],
...
});
參數(shù)說明:
- where:包含查找條件的對象,用于指定要匹配的屬性和值。
- include:指定關(guān)聯(lián)模型,用于在查詢中包含關(guān)聯(lián)的數(shù)據(jù)。
- offset:指定查詢的偏移量,用于分頁。
- limit:指定查詢的限制數(shù)量,用于分頁。
- order:指定查詢結(jié)果的排序順序。
- ...:其他可選參數(shù),用于進一步配置查詢。
使用 findAndCountAll 方法時,Sequelize 將根據(jù)指定的條件在數(shù)據(jù)庫中查找符合條件的所有記錄,并同時返回滿足條件的記錄數(shù)組和記錄總數(shù)。
const { count, rows } = await User.findAndCountAll({
where: { age: 25 },
include: [Post],
offset: 0,
limit: 10,
order: [['createdAt', 'DESC']]
});
console.log(count); // 符合條件的記錄總數(shù)
console.log(rows); // 符合條件的記錄數(shù)組
在上述代碼中,findAndCountAll 方法將根據(jù)年齡為 25 的條件在數(shù)據(jù)庫中查找用戶記錄,并返回滿足條件的記錄總數(shù)和記錄數(shù)組。include 參數(shù)用于指定要關(guān)聯(lián)的 Post 模型。
findAndCountAll 方法返回的結(jié)果是一個包含 count 和 rows 屬性的對象。count 表示符合條件的記錄總數(shù),rows 表示符合條件的記錄數(shù)組。
使用 findAndCountAll 方法可以方便地獲取滿足條件的記錄總數(shù)以及相應(yīng)的記錄數(shù)組,用于實現(xiàn)分頁和其他結(jié)果統(tǒng)計的需求。
count:查詢數(shù)量
可以使用 count 方法來獲取滿足指定條件的記錄數(shù)。它的語法如下:
Model.count({
where: { ... },
...
});
參數(shù)說明:
- where:包含查找條件的對象,用于指定要匹配的屬性和值。
- ...:其他可選參數(shù),用于進一步配置查詢。
使用 count 方法時,Sequelize 將根據(jù)指定的條件在數(shù)據(jù)庫中計算符合條件的記錄數(shù),并返回該記錄數(shù)。
const count = await User.count({
where: { age: 25 }
});
console.log(count); // 符合條件的記錄數(shù)
在上述代碼中,count 方法將根據(jù)年齡為 25 的條件在數(shù)據(jù)庫中計算符合條件的用戶記錄數(shù),并將其返回。該方法返回的結(jié)果將是一個表示符合條件的記錄數(shù)的整數(shù)值。
通過使用 count 方法,可以方便地獲取滿足條件的記錄數(shù),用于進行結(jié)果統(tǒng)計、分頁計算或其他相關(guān)處理。
min, max, sum:查詢最值
可以使用 min、max 和 sum 方法來進行最小值、最大值和求和計算。
這些方法可以通過調(diào)用模型的靜態(tài)方法來實現(xiàn),具體語法如下:
- min 方法用于計算指定屬性列的最小值:
Model.min('column', {
where: { ... },
...
});
- max 方法用于計算指定屬性列的最大值:
Model.max('column', {
where: { ... },
...
});
- sum 方法用于計算指定屬性列的總和:
Model.sum('column', {
where: { ... },
...
});
參數(shù)說明:
- 'column':要進行計算的屬性列的名稱。
- where:包含查找條件的對象,用于指定要匹配的屬性和值。
- ...:其他可選參數(shù),用于進一步配置查詢。
const minValue = await Model.min('column', {
where: { ... }
});
const maxValue = await Model.max('column', {
where: { ... }
});
const sumValue = await Model.sum('column', {
where: { ... }
});
console.log(minValue); // 最小值
console.log(maxValue); // 最大值
console.log(sumValue); // 總和
注意,這些方法將返回一個 Promise 對象,需要使用 await 或 .then() 來獲取計算結(jié)果。
create:創(chuàng)建數(shù)據(jù)
create() 方法用于在數(shù)據(jù)庫中創(chuàng)建一個新的記錄。它是 Sequelize 模型的一個實例方法,可以通過模型對象調(diào)用。
const newUser = await User.create({
name: 'John Doe',
email: 'john.doe@example.com',
age: 25,
});
使用 User.create() 方法創(chuàng)建一個名為 User 的新記錄。通過傳遞一個包含屬性和值的對象參數(shù),指定要創(chuàng)建的記錄的字段值。調(diào)用 create()方法會將新記錄插入到與模型關(guān)聯(lián)的數(shù)據(jù)庫表中,并返回一個表示新記錄的模型實例。
注意,create() 方法返回的是一個 Promise 對象,因此可以使用 await 關(guān)鍵字來等待創(chuàng)建操作的結(jié)果。如果創(chuàng)建成功,將返回包含新記錄數(shù)據(jù)的模型實例;如果創(chuàng)建失敗,將拋出一個異常。
create() 方法可以用于創(chuàng)建單個記錄,也可以用于批量創(chuàng)建多條記錄。如果想要批量創(chuàng)建多條記錄,可以將一個包含多個對象的數(shù)組傳遞給 create() 方法。
const newUsers = await User.create([
{
name: 'John Doe',
email: 'john.doe@example.com',
age: 25,
},
{
name: 'Jane Smith',
email: 'jane.smith@example.com',
age: 30,
},
]);
bulkCreate:批量創(chuàng)建數(shù)據(jù)
要批量添加數(shù)據(jù),可以使用 Model.bulkCreate() 方法。bulkCreate() 方法接受一個數(shù)組作為參數(shù),每個數(shù)組元素都表示要創(chuàng)建的記錄。
const newUsers = await User.bulkCreate([
{
name: 'John Doe',
email: 'john.doe@example.com',
age: 25,
},
{
name: 'Jane Smith',
email: 'jane.smith@example.com',
age: 30,
},
// 可以繼續(xù)添加更多對象...
]);
這里定義了一個 users 數(shù)組,其中包含要添加到數(shù)據(jù)庫的多個對象,每個對象表示一條記錄。然后,調(diào)用 User.bulkCreate() 方法,并傳遞 users 數(shù)組作為參數(shù),以批量添加這些記錄。
bulkCreate() 方法將會將數(shù)組中的每個對象插入到與模型關(guān)聯(lián)的數(shù)據(jù)庫表中,并返回一個包含新記錄的模型實例數(shù)組??梢愿鶕?jù)實際需求在 users 數(shù)組中添加任意數(shù)量的對象,以批量添加相應(yīng)數(shù)量的記錄。
bulkCreate() 和 create() 方法都可以用于創(chuàng)建多條數(shù)據(jù),但它們之間有一些區(qū)別:
- 性能差異:
- create() 方法在循環(huán)中逐個創(chuàng)建記錄,并執(zhí)行多個數(shù)據(jù)庫查詢操作。這意味著對于大量數(shù)據(jù)的批量創(chuàng)建,性能可能較低。
- bulkCreate() 方法會將所有記錄作為一個事務(wù)一次性插入數(shù)據(jù)庫,減少了數(shù)據(jù)庫查詢操作的次數(shù),因此在處理大量數(shù)據(jù)時可以更高效。
- 錯誤處理:
- create() 方法是可回滾的,即如果在循環(huán)中創(chuàng)建多個記錄時發(fā)生錯誤,可以選擇回滾已創(chuàng)建的記錄。
- bulkCreate() 方法默認情況下是不可回滾的,即如果在批量插入過程中發(fā)生錯誤,已插入的記錄將被保留。但你可以通過設(shè)置 individualHooks: true 選項來啟用回滾功能。
- 返回值:
- create() 方法在成功創(chuàng)建每條記錄后,返回一個表示該記錄的模型實例。
- bulkCreate() 方法在成功插入所有記錄后,返回一個包含所有新記錄的模型實例數(shù)組。
綜上所述,對于需要創(chuàng)建大量數(shù)據(jù)的情況,推薦使用 bulkCreate() 方法,以獲得更好的性能。但在某些情況下,例如需要在每次創(chuàng)建記錄時進行自定義操作或錯誤處理時,可以選擇使用 create() 方法。
update:更新數(shù)據(jù)
可以使用 update 方法來更新數(shù)據(jù)庫中的記錄。它的語法如下:
Model.update(values, {
where: { ... },
...
});
參數(shù)說明:
- values:一個包含要更新的屬性和值的對象。
- where:一個包含更新條件的對象,用于指定要匹配的屬性和值。
- ...:其他可選參數(shù),用于進一步配置更新。
使用 update 方法時,Sequelize 將根據(jù)指定的條件在數(shù)據(jù)庫中查找符合條件的記錄,并將相應(yīng)的屬性更新為指定的新值。
const result = await User.update(
{ age: 30, status: 'active' },
{
where: { id: 1 }
}
);
console.log(result); // 更新結(jié)果
在上述代碼中,update 方法將會將 id 屬性為 1 的用戶記錄的 age 和 status 屬性更新為新的值。
注意,update 方法返回一個表示更新結(jié)果的數(shù)組。該數(shù)組的第一個元素表示更新的行數(shù),第二個元素表示影響的行數(shù)。
const updatedRows = result[0];
const affectedRows = result[1];
console.log(updatedRows); // 更新的行數(shù)
console.log(affectedRows); // 影響的行數(shù)
通過使用 update 方法,可以方便地更新滿足條件的記錄,并可以靈活配置要更新的屬性和值。
注意,update 方法只能更新單條記錄。如果想要更新多條數(shù)據(jù),可以借助 Promise.all 來實現(xiàn):
// 查找需要更新的數(shù)據(jù)
const usersToUpdate = await User.findAll({ where: { status: 'active' } });
// 更新數(shù)據(jù)
await Promise.all(usersToUpdate.map(user => {
return user.update(
{ status: 'inactive' } // 更新的字段和值
);
}));
destroy:刪除數(shù)據(jù)
在 Sequelize 中,可以使用 destroy 方法來刪除數(shù)據(jù)庫中的記錄。它的語法如下:
Model.destroy({
where: { ... },
...
});
參數(shù)說明:
- where:包含刪除條件的對象,用于指定要匹配的屬性和值。
- ...:其他可選參數(shù),用于進一步配置刪除操作。
使用 destroy 方法時,Sequelize 將根據(jù)指定的條件在數(shù)據(jù)庫中查找符合條件的記錄,并將其從數(shù)據(jù)庫中刪除。
const result = await User.destroy({
where: { id: 1 }
});
console.log(result); // 刪除結(jié)果
在上述代碼中,destroy 方法將會刪除數(shù)據(jù)庫中 id 屬性為 1 的用戶記錄。該方法返回一個表示刪除結(jié)果的整數(shù)值。該值表示成功刪除的記錄數(shù)。
destroy 方法可以刪除滿足多個條件的記錄,從而批量刪除數(shù)據(jù)庫中的多個值。
const result = await User.destroy({
where: {
age: { [Op.gt]: 30 }, // 年齡大于30
status: 'inactive' // 狀態(tài)為inactive
}
});
console.log(result); // 刪除結(jié)果
上述代碼將會刪除數(shù)據(jù)庫中年齡大于30且狀態(tài)為inactive的用戶記錄。
模型聚合
模型聚合指的是使用 Sequelize 模型來執(zhí)行數(shù)據(jù)庫查詢,并對查詢結(jié)果進行聚合操作。通過使用 Sequelize 模型的聚合功能,你可以靈活地執(zhí)行各種統(tǒng)計和計算操作,并從數(shù)據(jù)庫中獲取所需的聚合結(jié)果。
模型聚合通常用于在查詢中應(yīng)用聚合函數(shù),以獲取關(guān)于數(shù)據(jù)集的匯總信息。聚合函數(shù)可以是內(nèi)置的數(shù)據(jù)庫函數(shù),也可以是自定義的函數(shù)。常見的聚合函數(shù)包括 SUM、COUNT、AVG、MAX、MIN 等。
假設(shè)有一個 Product 模型,它表示產(chǎn)品表。每個產(chǎn)品都有一個 price 字段,表示產(chǎn)品的價格?,F(xiàn)在,想計算所有產(chǎn)品的平均價格??梢允褂?Sequelize 的模型聚合功能來實現(xiàn):
const { fn, col } = require('sequelize');
const result = await Product.findOne({
attributes: [
[fn('AVG', col('price')), 'avgPrice']
]
});
這里使用 Product.findOne 查詢單個產(chǎn)品,并使用 attributes 參數(shù)指定要選擇的屬性列。我們使用 sequelize.fn 和 sequelize.col 創(chuàng)建了一個新的屬性列,將其命名為 avgPrice,并應(yīng)用了 AVG 聚合函數(shù)來計算價格的平均值。查詢結(jié)果將包含產(chǎn)品價格的平均值,以及對應(yīng)的屬性名稱。
注意,通過使用 sequelize.fn 和 sequelize.col,可以在查詢結(jié)果中創(chuàng)建一個虛擬的屬性列,用于存儲聚合函數(shù)計算得出的值(例如平均值、總和等)。這個虛擬字段只存在于查詢結(jié)果中,而不會對數(shù)據(jù)庫中的數(shù)據(jù)產(chǎn)生影響。換句話說,當執(zhí)行查詢并獲取結(jié)果時,每條結(jié)果將包含從數(shù)據(jù)庫中選擇的實際屬性列以及計算得出的虛擬屬性列(例如 avgPrice)。這些虛擬屬性僅在查詢結(jié)果中可見,不會直接影響數(shù)據(jù)庫中的數(shù)據(jù)。
sequelize.fn
sequelize.fn 是 Sequelize 提供的一個函數(shù),用于生成聚合函數(shù)的 SQL 片段。使用 sequelize.fn,可以在查詢中使用所有支持的聚合函數(shù)(如 COUNT、SUM、AVG、MIN、MAX 等)。
sequelize.fn 的語法如下:
sequelize.fn(functionName, args)
其中,functionName 是要調(diào)用的聚合函數(shù)名稱,如 COUNT、SUM、AVG、MIN、MAX 等;args 是可選的函數(shù)參數(shù),可以是列名稱或常量值。
sequelize.fn 可以與 sequelize.col 一起使用,用于生成復(fù)雜的 SQL 片段和查詢語句。它還可以與 where、group、having、order 等查詢選項一起使用。
sequelize.col
sequelize.col 用于生成對數(shù)據(jù)庫表中列的引用,使用 sequelize.col可以在查詢中引用特定的列。
sequelize.col 的語法如下:
sequelize.col(columnName)
其中,columnName 是要引用的列名稱。它可以是字符串形式的列名,也可以是一個包含表名和列名的數(shù)組。
下面使用 sequelize.col 引用 products 表中的 price 列:
const { col } = require('sequelize');
Product.findAll({
attributes: [
[col('price'), 'productPrice']
]
});
這里使用了 col 函數(shù)來生成一個對 price 列的引用,并將其映射到一個名為 productPrice 的屬性上。這樣,查詢結(jié)果中就會包含一個帶有別名的新屬性,它的值是 price 列的值。
屬性別名
[col('price'), 'productPrice'] 用于在查詢中定義屬性別名。它使用了數(shù)組的形式來表示一個屬性,并包含兩個元素:引用列的表達式和屬性別名。在這個例子中,col('price') 是一個 sequelize.col 函數(shù)調(diào)用,表示對 price 列的引用。'productPrice' 是一個字符串,表示希望將 price 列的值映射到一個名為 productPrice 的屬性上。這樣,返回的結(jié)果將會包含一個名為 productPrice 的屬性,其中的值是對應(yīng)的 price 列的值。
選擇所有列
col('*') 表示引用表中的所有列。通常,在 Sequelize 中,我們可以在 attributes 數(shù)組中使用它來選擇查詢結(jié)果中要返回的列。
const { col } = require('sequelize');
Product.findAll({
attributes: [
col('*')
]
});
這里使用 col('*') 來引用所有列。這意味著查詢結(jié)果將包含表中的每個列。
請注意,使用 col('*') 將返回表中的所有列,包括主鍵、外鍵和其他所有列。如果只想選擇特定的列,可以將列名以字符串的形式傳遞給 col 函數(shù),如 col('columnName')。
sequelize.literal
在 Sequelize 中,可以使用 sequelize.literal 方法來自定義聚合函數(shù)或任何其他數(shù)據(jù)庫原生函數(shù)。
sequelize.literal 允許在查詢中添加原始的 SQL 代碼,包括自定義的聚合函數(shù)??梢酝ㄟ^將 SQL 代碼作為字符串傳遞給 sequelize.literal 來實現(xiàn)。
下面來使用 sequelize.literal 自定義一個名為 customCount 的聚合函數(shù):
const { literal } = require('sequelize');
Product.findAll({
attributes: [
[literal('COUNT(*) + 1'), 'customCount']
]
});
這里使用了 literal 函數(shù)來生成一個原始的 SQL 表達式 COUNT(*) + 1,并將其映射到一個名為 customCount 的屬性上。
請注意,使用 sequelize.literal 時需小心確保代碼的安全性和正確性,以避免潛在的風險和錯誤。請謹慎使用,并確保仔細檢查和測試自定義函數(shù)的邏輯。
模型關(guān)聯(lián)
在 Sequelize 中,模型關(guān)聯(lián)是指在不同表之間建立起的關(guān)系,使得可以通過一個模型對象訪問到與其相關(guān)聯(lián)的其他模型對象的數(shù)據(jù)。
Sequelize 支持多種類型的模型關(guān)聯(lián),包括一對一(One-to-One)、一對多(One-to-Many)和多對多(Many-to-Many)等。通過定義模型之間的關(guān)聯(lián)關(guān)系,我們可以方便地執(zhí)行跨表查詢、創(chuàng)建、更新以及刪除操作,而無需手動編寫復(fù)雜的 JOIN 查詢。
在 Sequelize 中,定義模型關(guān)聯(lián)的方法有以下幾種:
- hasOne:定義一對一的關(guān)聯(lián)關(guān)系。該方法通常用于聲明一個模型擁有唯一的關(guān)聯(lián)模型。
- hasMany:定義一對多的關(guān)聯(lián)關(guān)系。該方法通常用于聲明一個模型擁有多個關(guān)聯(lián)模型。
- belongsToMany:定義多對多的關(guān)聯(lián)關(guān)系。該方法用于建立兩個模型之間的多對多關(guān)聯(lián)關(guān)系,需要通過一個中間模型來實現(xiàn)。
- belongsTo:定義一對一或一對多的關(guān)聯(lián)關(guān)系。該方法通常用于聲明一個模型屬于另一個模型,也可以用于建立模型之間的一對多關(guān)聯(lián)關(guān)系。
例如,假設(shè)有兩個模型:User(用戶)和Post(帖子)。一個用戶可以擁有多篇帖子,而一篇帖子只能屬于一個用戶。在這種情況下,我們可以通過一對多的關(guān)系來建立模型關(guān)聯(lián)。
可以通過在模型定義中使用 hasMany 和 belongsTo 方法來定義一對多的關(guān)聯(lián)關(guān)系。下面是一個示例:
// User 模型定義
const User = sequelize.define('User', {
// ...其他屬性
});
// Post 模型定義
const Post = sequelize.define('Post', {
// ...其他屬性
});
// 建立一對多關(guān)聯(lián)
User.hasMany(Post, { foreignKey: 'userId' });
Post.belongsTo(User, { foreignKey: 'userId' });
在上述示例中,User.hasMany(Post) 表示用戶模型擁有多個帖子,Post.belongsTo(User) 表示帖子模型屬于一個用戶。通過指定外鍵 userId,Sequelize 將根據(jù)該外鍵進行關(guān)聯(lián)查詢。
通過建立模型關(guān)聯(lián),可以使用框架提供的方法來執(zhí)行聯(lián)表查詢,例如:
// 查詢用戶及其所有帖子
const user = await User.findByPk(userId, { include: Post });
// 查詢帖子及其所屬用戶
const posts = await Post.findAll({ include: User });
這樣就可以方便地在相關(guān)聯(lián)的模型之間進行數(shù)據(jù)查詢和操作。