I have a use case where I need to present a list of records with a join value from each record. This is usually done with a JOIN in SQL.
To provide some context, I would use the TILApp. I have modified the code in Chapter 21 so that I could have an index webpage where the creator’s name for each acronym is displayed alongside the acronym. The code works, but I am unsure of the efficiency:
func indexHandler(_ req: Request) throws -> Future<View> {
return Acronym.query(on: req)
.all()
.flatMap(to: View.self) { acronyms in // required in order to get the related user for another query??
return flatMap(
to: View.self,
req.future(acronyms), // wrap the acronyms back into a future in order to flatMap it with the future from user??
acronyms.map { $0.user.get(on: req) }.flatten(on: req)) { acronyms, users in
let acronymsData: [AcronymData]? = acronyms.isEmpty ? nil : acronyms.map { acronym in
let user = users.filter { $0.id == acronym.userID }.first
return AcronymData(short: acronym.short, long: acronym.long, creatorName: user?.name ?? "")
}
let userLoggedIn = try req.isAuthenticated(User.self)
let showCookieMessage = req.http.cookies["cookies-accepted"] == nil
let context = IndexContext(title: "Homepage",
acronyms: acronymsData,
userLoggedIn: userLoggedIn,
showCookieMessage: showCookieMessage)
return try req.view().render("index", context)
}
}
}
struct AcronymData: Encodable { // View Model using primitives
let short: String
let long: String
let creatorName: String
}
struct IndexContext: Encodable {
let title: String
let acronyms: [AcronymData]?
let userLoggedIn: Bool
let showCookieMessage: Bool
}
My question is:
Is there a more concise and elegant way to perform a join query which will fetch the user (perhaps even selected properties of user)?