vapor 实践

vapor fluent[sqlite] relations

2018-10-04  本文已影响10人  搞好关系

父子关系/一对多/Parent-Child/one-many

星系中有很多恒星,怎么表示这种关系呢?


image.png
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
下面我们就来看一例子:搜寻✨时往往会给他们做个标签---类地行星 液体星球等,那我们怎么来关联呢

image.png
上图中是太阳系中星球的表示
我们创建了三个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: ...)
上一篇 下一篇

猜你喜欢

热点阅读