Fluent query with Unix Timestamps with Vapor 4

225 Views Asked by At

I am new to Vapor/Fluent. I have a model with two timestamp fields like this:

import Fluent
import Vapor

final class User: Model, Content {

    @Timestamp(key: "updated_at", on: .update, format: .unix)
    var modificationDate: Date?

    @Timestamp(key: "deleted_at", on: .delete, format: .unix)
    var deletionDate: Date?
}

I want to write a Fluent query for users based on these dates, i.e. get all users with modificationDate or deletionDate not nil and within a given time interval. Something like this:

func getUpdatedOrDeletedUsers(startDate: Date, endDate: Date) async throws -> [User] {
   let interval: Range<Date> = startDate..<endDate
   return try await User.query(on: request.db)
                        .withDeleted()
                        .filter((\.$modificationDate != nil && interval.contains(\.$modificationDate!)) || (\.$deletionDate != nil && interval.contains(\.$deletionDate!)))
                        .all()
}

Unfortunately, this kind of syntax does not seem to be allowed. After reading the documentation I came up with this solution:

func getUpdatedOrDeletedUsers(startDate: Date, endDate: Date) async throws -> [User] {
   return try await User.query(on: request.db)
                        .withDeleted()
                        .group(.or) { group in
                           group.group(.and) { group in
                              group.filter(\.$modificationDate != nil)
                                   .filter(\.$modificationDate >= startDate)
                                   .filter(\.$modificationDate < endDate)
                           }
                           .group(.and) { group in
                              group.filter(\.$deletionDate != nil)
                                   .filter(\.$deletionDate >= startDate)
                                   .filter(\.$deletionDate < endDate)
                           }
                        }
                        .all()
}

But this does not seem very readable. I thought about making two separate queries, but I think that might have a negative impact on performance. Is this the right way to do it with Fluent? Is there a better way?

0

There are 0 best solutions below