What I mean by "parent/child" is a one to many relationship and "siblings" would be describing a many to many relationship. It's extremely common to want to get all the objects owned by another object (get all posts made by a user), or the parent of an object (get the user who made this post), so ORMs will often have features to make that sort of operation easier.
extension Galaxy {
// this galaxy's related planets
var planets: Children<Galaxy, Planet> {
return children(\.galaxyID)
}
}
// to retrieve all Planets in a Galaxy
let planets = galaxy.planets.query(on: ...).all()
GRDB has currently three Associations: hasOne, hasMany, and belongsTo (inspired by ActiveRecord).
To get all planets in a Galaxy, you'd write:
extension Galaxy {
/// An association (backed by database foreign keys)
static let planets = hasMany(Planet.self)
/// The request for the planets of the galaxy
var planets: QueryInterfaceRequest<Planet> {
return request(for: Galaxy.planets)
}
}
let galaxy: Galaxy = ...
let planets: [Planet] = try galaxy.planets.fetchAll(db)
Associations can be filtered, aggregated, observed...
let inhabitablePlanets: [Planet] = try galaxy
.planets
.filter(...)
.fetchAll(db)
let bigGalaxies: [Galaxy] = try Galaxy
.having(Galaxy.planets.count > 1e10) // it's a big SQLite database ;-)
.fetchAll(db)
let observer = try ValueObservation
.trackingAll(galaxy.planets)
.start(in: ...) { planets: [Planet] in
print("planets have changed")
}
You can also join tables and build requests like "give me all galaxies with their number of planets", or "give me all planets with their galaxies", or "give me all planets whose galaxy is closer than N light years".
There are features which are still to be implemented:
Many-to-many associations. You currently need to model them out of two one-to-many associations.
Indirect associations, such as "one galaxy has many planets through its stars". You currently need to provide the full path to deeply nested records.
Requests of trees, such as "give me all galaxies with their planets". See this issue for more information and a workaround.
Please have a look at the doc. And come back if you have any question!