父子关系/一对多/Parent-Child/one-many
星系中有很多恒星,怎么表示这种关系呢?
struct Galaxy: SQLiteModel {
var id:Int? = nil
var name: String
}
struct Planet: SQLiteModel {
var id: Int?
var name: String
var galaxyID: Int
}
fluent 中通过extension
在其中添加Parent和Children来实现这种特殊的关联关系
extension Galaxy{
var planets: Children<Galaxy, Planet>{
return children(\.galaxyID)
}
}
extension Planet{
var galaxy: Parent<Planet, Galaxy>{
return parent(\.galaxyID)
}
}
其中Parent和Children都是一种<From, To>
的关系通过keypath来明确怎么关联
使用
var galaxy: Galaxy?
galaxy?.planets.query(on: <#T##DatabaseConnectable#>)
var planet: Planet?
planet!.galaxy.get(on: <#T##DatabaseConnectable#>)
兄弟关系/多对多/ many-many
在这种关系中是两个独立的Model,为了将他们直观的关联需要一个第三方的方式将其联系起来,我们称之为pivot
下面我们就来看一例子:搜寻✨时往往会给他们做个标签---类地行星 液体星球等,那我们怎么来关联呢
上图中是太阳系中星球的表示
我们创建了三个Model--Planet,Tag, PlanetTag:
struct Planet: SQLiteModel {
var id: Int?
var name: String
var galaxyID: Int
}
struct Tag: SQLiteModel {
var id: Int?
var name: String
}
struct PlanetTag: SQLitePivot {
static var leftIDKey: WritableKeyPath<PlanetTag, Int> = \.planetID
static var rightIDKey: WritableKeyPath<PlanetTag, Int> = \.tagID
typealias Left = Planet
typealias Right = Tag
var id: Int?
var planetID: Int
var tagID: Int
}
PlanetTag作为一个中间纽带将Tag和Palnet关联了起来:我们可以通过这种关系搜寻具有某种Tag的Planet也可以通过Planet来查看大致发现了哪些类型的星球
同样的Sibling关系也是通过extension
中添加
extension Planet {
// this planet's related tags
var tags: Siblings<Planet, Tag, PlanetTag> {
return siblings()
}
}
extension Tag {
// all planets that have this tag
var planets: Siblings<Tag, Planet, PlanetTag> {
return siblings()
}
}
Siblings是一种<From, To, Through>,可以解释为将A和B通过C进行关联
使用
var p: Planet?
p?.tags.query(on: <#T##DatabaseConnectable#>)
var tag: Tag?
tag?.planets.query(on: <#T##DatabaseConnectable#>)
修改关联关系 Modifiable Pivot
Pivot要想具有可修改功能需要conformModifiablePivot
extension PlanetTag: ModifiablePivot {
init(_ planet: Planet, _ tag: Tag) throws {
planetID = try planet.requireID()
tagID = try tag.requireID()
}
}
使用
let planet: Planet = ...
let tag: Tag = ...
planet.tags.attach(tag, on: ...)