I have a two models in Vapor using Fluent as the ORM, one is a Transaction
and the other is an Invoice
. The Transaction
model has the below:
@OptionalParent(key: "invoice_id")
var invoice: Invoice?
So the invoice
property can be nil or assigned to an Invoice
model. My question is how do I query for Transaction
's where the invoice
can be nil
OR can be assigned to an Invoice
where I can check if the invoice
is active (I have an isActive
property on the Invoice
model)?
I tried reading about the below:
https://docs.vapor.codes/fluent/query/
https://forums.swift.org/t/vapor-fluent-query-support-and-xor/32647
So far I'm trying to do like so:
try? await Transaction.query(on: request.db)
.with(\.$invoice)
.sort(\.$dateCreated, .descending)
.all()
I'm then looping through all the transaction
s and I'm skipping what is not having isActive
set to true
.
I also tried the following:
let transactions = (try? await Transaction.query(on: request.db)
.with(\.$invoice)
.group(.or) { group in
group
.filter(\Transaction.$invoice.$id !~ (try inactiveInvoices.map { try $0.requireID() }))
.filter(\Transaction.$invoice.$id == nil)
}
.sort(\.$dateCreated, .descending)
.all()) ?? []
It works...but it has a lot of queries in it. Is there a way to simplify it?
I basically want to check if it's nil
or if the isActive
property on invoice
is true
from the query itself. Is this possible in Vapor? Any help is appreciated!
I got a solution that works! I need to use a LEFT OUTER JOIN which can be done by specifying .left
for the method
argument on the join
, like so:
let transactions = (try? await Transaction.query(on: request.db)
.with(\.$invoice)
.join(Invoice.self, on: \Transaction.$invoice.$id == \Invoice.$id, method: .left)
.group(.or) { group in
group
.filter(Invoice.self, \Invoice.$isActive == true)
.filter(\.$invoice.$id == nil)
}
.sort(\.$dateCreated, .descending)
.all()) ?? []