又称“拥有并属于多个”
多对多关联表明,一条记录可以与许多其他记录相关联,反之亦然。这种类型的关联涉及创建连接表来跟踪记录之间多个链接。当 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'
}
}
};
为了将记录关联在一起,使用 Model 方法.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
数据存储中,您将在wishlist
属性定义中添加dominant: true
。相反,在wishlistedBy
属性中添加dominant: true
将导致连接表在ourRedis
数据存储中创建。
几个因素可能会影响您在何处创建连接表的决定
dominant
。同样,法规或合规性问题也可能会影响您的决定。如果关联包含敏感的患者信息(例如,Patient
和Medicine
之间的关联),您需要确保所有相关数据保存在一个特定数据库中而不是另一个数据库中(在这种情况下,Patient
很可能是dominant
)。Medicine
连接到只读的供应商数据库),您将无法写入它,因此您需要确保您的关系数据可以安全地持久化在另一侧。