Vapor 4中基于Unix时间戳的Fluent多条件查询优化咨询
解答
你的分组查询写法完全符合Fluent规范
Fluent的查询构建器本身就是通过嵌套的group(.or)/group(.and)来处理复杂逻辑组合的,这是官方推荐的标准写法,生成的SQL语句正确且高效,完全符合规范。
更优的实现方式(以提升可读性为主)
你可以通过封装或代码结构优化来提升可读性,同时保留一次查询的性能优势:
方案1:封装为QueryBuilder扩展
把两个时间区间的判断逻辑封装成扩展方法,让主查询代码更简洁:
extension QueryBuilder where Model == User { func modificationDateIn(_ range: Range<Date>) -> Self { return group(.and) { $0.filter(\.$modificationDate != nil) .filter(\.$modificationDate >= range.lowerBound) .filter(\.$modificationDate < range.upperBound) } } func deletionDateIn(_ range: Range<Date>) -> Self { return group(.and) { $0.filter(\.$deletionDate != nil) .filter(\.$deletionDate >= range.lowerBound) .filter(\.$deletionDate < range.upperBound) } } }
主函数简化后:
func getUpdatedOrDeletedUsers(startDate: Date, endDate: Date) async throws -> [User] { let interval = startDate..<endDate return try await User.query(on: request.db) .withDeleted() .group(.or) { $0.modificationDateIn(interval) .deletionDateIn(interval) } .all() }
方案2:优化原代码的可读性
如果不想写扩展,只需调整代码结构和添加注释,就能让逻辑更清晰:
func getUpdatedOrDeletedUsers(startDate: Date, endDate: Date) async throws -> [User] { return try await User.query(on: request.db) .withDeleted() .group(.or) { orGroup in // 条件1:modificationDate非空且在区间内 orGroup.group(.and) { modGroup in modGroup.filter(\.$modificationDate != nil) .filter(\.$modificationDate >= startDate) .filter(\.$modificationDate < endDate) } // 条件2:deletionDate非空且在区间内 orGroup.group(.and) { delGroup in delGroup.filter(\.$deletionDate != nil) .filter(\.$deletionDate >= startDate) .filter(\.$deletionDate < endDate) } } .all() }
为什么不建议拆分两次查询?
拆分查询会带来两个问题:
- 额外的数据库往返请求,性能不如一次合并查询;
- 若存在同时满足两个条件的用户,两次查询会返回重复结果,需要额外做去重处理,增加代码复杂度。
内容的提问来源于stack exchange,提问作者MikeElmwood
相关产品推荐
相关产品推荐

