又稱「Has and Belongs To Many」
多對多關聯是指一個記錄可以與多個其他記錄關聯,反之亦然。這種關係類型需要建立一個連接表,以追蹤記錄之間的多個連結。當 Waterline 偵測到兩個模型具有集合屬性,這些屬性透過其 via
鍵相互指向時(請參閱下文),它會自動為您建立連接表。
via
鍵由於您可能希望一個模型在另一個模型上有多個多對多關聯,因此 collection
屬性上需要一個 via
鍵。via
鍵指示多對多關聯另一側的相關屬性。
使用 User
和 Pet
範例,讓我們看看如何建立一個綱要,其中 User
可能有多個 Pet
記錄,而 Pet
可能有多個擁有者。
// myApp/api/models/User.js
// A user may have many pets
module.exports = {
attributes: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
// Add a reference to Pet
pets: {
collection: 'pet',
via: 'owners'
}
}
};
// myApp/api/models/Pet.js
// A pet may have many owners
module.exports = {
attributes: {
breed: {
type: 'string'
},
type: {
type: 'string'
},
name: {
type: 'string'
},
// Add a reference to User
owners: {
collection: 'user',
via: 'pets'
}
}
};
要將記錄關聯在一起,可以使用模型方法 .addToCollection()。這允許您設定將要關聯的記錄的主鍵。
// To add a Pet to a user's `pets` collection where the User has an id of
// 10 and the Pet has an id of 300.
await User.addToCollection(10, 'pets', 300);
您也可以一次新增多個寵物
await User.addToCollection(10, 'pets', [300, 301]);
使用 .removeFromCollection() 方法移除關聯同樣容易。它的運作方式與 addToCollection
相同
// To remove a User from a pet's collection of owners where the User has an id of
// 10 and the Pet has an id of 300.
await Pet.removeFromCollection(300, 'owners', 10);
您也可以一次移除多個擁有者
await Pet.removeFromCollection(300, 'owners', [10, 12]);
請注意,從多對多關係的一側新增或移除關聯記錄將自動影響另一側。例如,使用 .addToCollection()
將記錄新增到 User
模型記錄的 pets
屬性,將立即影響連結的 Pet
記錄的 owners
屬性。
若要傳回透過 .find()
或 .findOne()
檢索的記錄以及關聯的集合,請使用 .populate()
方法。
在大多數情況下,Sails 將能夠在沒有您的任何輸入的情況下為多對多關聯建立連接表。但是,如果關聯中的兩個模型使用不同的資料儲存區,您可能想要選擇哪一個應該包含連接表。您可以透過在關係中的其中一個關聯上設定 dominant: true
來執行此操作。
考慮以下模型
// User.js
module.exports = {
datastore: 'ourMySQL',
attributes: {
email: 'string',
wishlist: {
collection: 'product',
via: 'wishlistedBy'
}
}
};
// Product.js
module.exports = {
datastore: 'ourRedis',
attributes: {
name: 'string',
wishlistedBy: {
collection: 'user',
via: 'wishlist'
}
}
};
在這種情況下,User
和 Product
記錄存在於不同的資料庫中。預設情況下,Sails 將任意選擇一個資料儲存區(ourMySQL
或 ourRedis
中的任何一個)來包含連接表,該表將 User
的 wishlist
屬性連結到 Product
的 wishlistedBy
屬性。為了強制連接表存在於 ourMySQL
資料儲存區中,您需要將 dominant: true
新增到 wishlist
屬性定義中。相反地,將 dominant: true
新增到 wishlistedBy
屬性將導致在 ourRedis
資料儲存區中建立連接表。
有幾個因素可能會影響您決定在哪裡建立連接表
dominant
。同樣地,法規或合規性問題也可能會影響您的決定。如果關係包含敏感的患者資訊(例如,Patient
和 Medicine
之間的關係),您會希望確保所有相關資料都保存在一個特定的資料庫中,而不是另一個資料庫中(在這種情況下,Patient
很可能成為 dominant
)。Medicine
連接到唯讀的供應商資料庫),您將無法寫入它,因此您需要確保您的關係資料可以安全地持久保存在另一側。