I have 3 tables, LastName, MiddleName and FirstName... FirstName has MiddleNameID as Parent, MiddleName has LastName.id as parent
Models look like this
final class LastName: Model, Content {
static let schema = "lastnames"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
@Children(for: \.$lastname)
var middle_names: [MiddleName]
init() { }
init(id: UUID? = nil, name: String) {
self.id = id
self.name = name
}
}
final class MiddleName: Model, Content {
static let schema = "middlenames"
@ID(key: .id)
var id: UUID?
@Parent(key: "last_name_id")
var lastname: LastName
@Field(key: "name")
var name: String
@Children(for: \.$middleNameId)
var firstNames: [FirstName]
init() { }
init(id: UUID? = nil, lastname: LastName, name: String ) {
self.id = id
self.lastname = lastname
self.name = name
}
}
final class FirstName: Model, Content {
static let schema = "firstnames"
@ID(key: .id)
var id: UUID?
@Parent(key: "middle_name_id")
var middleNameId: MiddleName
@Field(key: "name")
var name: String
init() { }
init(id: UUID? = nil, middleNameId: MiddleName, name: String) {
self.id = id
self.middleNameId = testBundleId
self.name = name
}
}
And i want the query such as give me all the first name records where lastname == Smith AND/OR middle == James... not sure how can I do a multiple join's using Fluent DSL? or maybe give me all first name which matches something from Middle Name and/or last name
if I had to write a SQL query probably will look like this
SELECT DISTINCT ON (ln.id, mn.id)
ln.name, mn.name, fn.*
FROM last_name ln
LEFT JOIN middle_name mn ON ln.id = mn.last_name_id
LEFT JOIN first_name fn ON fn.middle_name_id = mn.id
WHERE ( mn.name <> '' AND fn.name <> '' ) AND
(true AND ln.name ~ 'smith')
ORDER BY ln.id, mn.id, fn.id
You can do this in a Fluent query, something like:
return Lastname.query(on: req)
.filter(\.$name == "Smith")
.with(\.$middle_names) { $0.with(\.$firstnames) }
.all()
.flatMap { wholeNames in
let result = wholeNames.filter { $0.middle_names.contains("James") }
// continue
}
This will give you all the Smiths who have a middle name of James. You can use it as the basis for the OR variant. It works by first filtering the surnames for Smith and then the with
joins the middle name, but the closure ensures first names are joined as well.
I don't think there is a way of building the middle-name filter into the query, so I think you have to do it as I have shown.