vapor fluent[sqlite] relations

父子关系/一对多/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: ...)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 12,129评论 0 10
  • 快要高考了,我劝孩子家长们在把孩子送出去之前和孩子好好喝一顿。让宝宝们测一下酒量,为什么?因为单纯的宝宝们不会知道...
    虞熙阅读 2,994评论 3 4
  • 上周一个“相亲对象”结婚了,我竟然还去参加了婚礼。3年后的再见面,他瘦了很多。新娘子也没有大家说的那样不漂亮,反而...
    薄荷摩卡阅读 1,228评论 0 1
  • 我是共学共享、樊登读书会贺州授权点的姗姗,这是原创文第110篇 昨天我们和书店的一位志愿者沟通,这位志愿者到书店到...
    共学共享阅读 5,355评论 0 1
  • 看完三页 答应你的 乖乖关灯睡觉 好了不闹 不能拥抱 我也乖乖睡觉 抑制不住躁动的心 想冲上去扑倒你 还是乖乖睡觉...
    取名字啥的真的好烦阅读 1,417评论 0 0