I am using Vapor 4 and I have the following MySQL Database structure: A City has reference to a POI and a POI has a reference to a Translation. How should I use the join statement. So that I get the Translation in the city model?
public final class City: Model {
public static let schema = "cities"
@ID(custom: "id")
public var id: Int?
@Parent(key: "poi_id")
public var poi: POI
}
public final class POI: Model {
public static let schema = "b_pois"
@ID(custom: "id")
public var id: Int?
@OptionalParent(key: "name_translation_id")
public var nameTranslation: Translation?
}
public final class Translation: Model {
public static let schema = "b_translations"
@ID(custom: "id")
public var id: Int?
@Field(key: "english")
public var english: String
@OptionalField(key: "german")
public var german: String?
...
}
When I use the following query I expect the city model to have the value:
let cities = try await City.query(on: dataBase)
.join(POI.self, on: \POI.$id == \City.$poi.$id)
.join(Translation.self, on: \POI.$nameTranslation.$id == \Translation.$id)
.with(\.$poi)
.filter(City.self, \.$population >= population)
.all()
// expected:
cities.first!.poi.nameTranslation != nil
// or
cities.first!.$poi.$nameTranslation.value != nil
But even though the database has a value and poi ist not nil I don't retrieve a value for the name translation. Am I missing something?
I need something like:
.with(\.$poi.$nameTranslation)
But this is not possible.
You can achieve what you want by nesting with
. Something like:
.with(\.$poi) { $0.with(\.$nameTranslation) }
Should do the job nicely!
You don't need the explicit JOIN
s if you are using Parent
/OptionalParent
, etc. Let fluent take care of it. You can then access the translated name (with suitable guard
/if let
, etc.):
city.poi.nameTranslation
Your query should boil down to:
let cities = try await City.query(on: dataBase)
.with(\.$poi) { $0.with(\.$nameTranslation) }
.filter(City.self, \.$population >= population)
.all()
In vapor terms, this is called 'nested eager loading' and is documented here.