關聯 (Association)
直接子類別
在 sequelize 中建立關聯是透過在模型 (來源) 上呼叫 belongsTo / hasOne / hasMany / belongsToMany 函數之一來完成的,並提供另一個模型作為函數的第一個引數 (目標)。
- hasOne - 在目標上新增外鍵,並在來源上新增單數關聯 mixins。
- belongsTo - 在來源上新增外鍵和單數關聯 mixins。
- hasMany - 在目標上新增外鍵,並在來源上新增複數關聯 mixins。
- belongsToMany - 建立具有聯結表的 N:M 關聯,並在來源上新增複數關聯 mixins。聯結表是使用 sourceId 和 targetId 建立的。
建立關聯將為屬性新增外鍵約束。所有關聯在更新時使用 CASCADE
,在刪除時使用 SET NULL
,但 n:m 除外,它在刪除時也使用 CASCADE
。
建立關聯時,您可以透過 as
選項提供別名。如果同一個模型關聯了兩次,或者您希望將關聯稱為目標模型名稱以外的名稱,這會很有用。
例如,考慮使用者有多個圖片,其中一張是他們的個人資料圖片的情況。所有圖片都有一個 userId
,但此外,使用者模型也有一個 profilePictureId
,以便能夠輕鬆載入使用者的個人資料圖片。
User.hasMany(Picture)
User.belongsTo(Picture, { as: 'ProfilePicture', constraints: false })
user.getPictures() // gets you all pictures
user.getProfilePicture() // gets you only the profile picture
User.findAll({
where: ...,
include: [
{ model: Picture }, // load all pictures
{ model: Picture, as: 'ProfilePicture' }, // load the profile picture.
// Notice that the spelling must be the exact same as the one in the association
]
})
為了完全控制 sequelize 新增的外鍵欄位,您可以使用 foreignKey
選項。它可以是一個指定名稱的字串,也可以是一個與傳遞給 sequelize.define
的類型定義等效的物件。
User.hasMany(Picture, { foreignKey: 'uid' })
現在,Picture 中的外鍵欄位將被稱為 uid
,而不是預設的 userId
。
User.hasMany(Picture, {
foreignKey: {
name: 'uid',
allowNull: false
}
})
這指定 uid
欄位不能為空。在大多數情況下,這將已經被 sequelize 自動建立的外鍵約束所涵蓋,但在外鍵被停用(例如,由於循環參照)的情況下很有用(請參閱下面的 constraints: false
)。
在提取關聯模型時,您可以限制查詢只載入一些模型。這些查詢的撰寫方式與 find
/findAll
的查詢相同。要僅取得 JPG 格式的圖片,您可以執行
user.getPictures({
where: {
format: 'jpg'
}
})
有多種方式可以更新和新增新的關聯。繼續我們使用者和圖片的範例
user.addPicture(p) // Add a single picture
user.setPictures([p1, p2]) // Associate user with ONLY these two picture, all other associations will be deleted
user.addPictures([p1, p2]) // Associate user with these two pictures, but don't touch any current associations
如果您的關聯模型具有單個主鍵,則不必將完整的物件傳遞給關聯函數
user.addPicture(req.query.pid) // Here pid is just an integer, representing the primary key of the picture
在上面的範例中,我們指定使用者屬於他的個人資料圖片。從概念上講,這可能沒有意義,但由於我們希望將外鍵新增到使用者模型中,因此這是執行此操作的方式。
請注意,我們也為個人資料圖片指定了 constraints: false
。這是因為我們從使用者新增到圖片的外鍵 (profilePictureId),以及從圖片新增到使用者的外鍵 (userId)。如果我們在兩者都新增外鍵,它將建立一個循環依賴,sequelize 將不知道首先建立哪個表,因為使用者依賴圖片,而圖片依賴使用者。這些問題會在模型同步到資料庫之前由 sequelize 檢測到,並且您會收到類似 Error: Cyclic dependency found. 'users' is dependent of itself
的錯誤。如果遇到這種情況,您應該停用某些約束,或完全重新考慮您的關聯。