Relations可以让两个数据库通过外键进行关联。这在基础的SQL数据库很常见,但是也可以用于NoSQL的数据库中。
Fluent的Relations有以下几种:
- Parent (BelongsTo)
- Children (HasMany, HasOne)
- Siblings (ManyToMany, BelongsToMany)
Parent
一个实体通过给另一个实体外部键关联起来,就构成了父关系(parent)。如下所示:
pets
- id
- owner_id
- name
- type
owner
- id
- name
这里每个pets都可以拥有一个owner。 要从pet访问owner,请调用.parent()。ps:owner将id定义为owner_id作为外键与pets关联起来,那么owner就是pets的parent。一个pets有且只有一个owner。(也就是一个儿子有且只有有一个爹)
let pet: Pet = ...
let owner = try pet.parent(pet.ownerId, Owner.self).get()
parent()的参数是外键和parent的类型。
Convenience
为了使查询parent更简单,我们给model添加一个方法:
extension Pet {
func owner() throws -> Parent<Owner> {
return try parent(ownerId)
}
}
在扩展了Pet类之后,我们不需要再在ownerId前加pet.了。另外,由于返回类型已经确定,所以也不需要Owner.self这个参数了。
Parent<T>类型是一个可查询的对象,也就意味着同样可以使用delete和filter对parent进行操作。
try pet.owner().delete()
获取parent则需要调用get():
let owner = try pet.owner().get()
Children
Children和Parent关系相反,总结之前的例子,也可以通过owner查询pets。
let owner: Owner = ...
let pets = owner.children(Pet.self).all()
参数只有child的类型。
Convenience
和Parent一样,扩展添加一个查询child的方法:
extension Owner {
func pets() throws -> Children<Pet> {
return try children()
}
}
返回值中明确了返回类型,所以也不再需要Pet.self这个参数了。
Children<T>也是可查询对象,所以可以调用first(),all(),filter()等方法。
let coolPets = try owner.pets().filter("type", .in, ["Dog", "Ferret"]).all()
Siblings(兄弟姐妹😁)
Siblings不同于Parent和Child关系,需要Pivot类作为枢纽。
举个例子,假设我们要让我们的pets有多个toys。 但是我们也希望toys能被多种pets共享。 我们需要一个Pivot实体(也就是单独创建一个关联表)。
pets
- id
- type
- owner_id
toys
- id
- name
pets_toys
- id
- pet_id
- toy_id
如你所见,创建了一个实体:pets_toys或者是Pivot<Pet, Toy>。
Convenience
给Pet添加一个快捷方法:
extension Pet {
func toys() throws -> Siblings<Toy> {
return try siblings()
}
}
反过来给Toy也添加一个:
extension Toy {
func pets() throws -> Siblings<Pet> {
return try siblings()
}
}
然后就可以像查询child关系那样去查询了:
let pet: Pet = ...
let toys = pet.toys().all()
下面是创建“多对多”关系的方法:
var toy: Toy = ... // Create a new toy
try toy.save() // Save the toy to the db
var pet: Pet = ... // Create a new pet
try pet.save() // Save the pet to the db
// Link them together in the db
var pivot = Pivot<Toy, Pet>(toy, pet) // Create the relationship
try pivot.save() // Save the relationship to the db
Preparation
为了备份通过Pivot建立的关系,只要简单的将这个pivot添加到Droplet的preparations中。
let drop = Droplet()
drop.preparations += [
Toy.self,
Pet.self,
Pivot<Toy, Pet>.self
]
<b>总结:</b>这节主要介绍了表之间的关联关系,以及如何通过关联关系进行数据查询。最后介绍了如何对Pivot进行备份。






网友评论