如何使用Fluent ORM实现嵌套父表多表关联查询
注:你提供的
FirstName模型初始化方法存在笔误,需要将self.middleNameId = testBundleId修改为self.middleNameId = middleNameId,否则会编译报错。
Fluent多表关联查询实现方案
1. 核心需求实现(筛选lastName=Smith 且/或 middleName=James的FirstName记录)
直接从FirstName模型出发,逐层关联父表即可实现多表join查询,代码如下:
FirstName.query(on: db) // 关联MiddleName父表 .join(parent: \.$middleNameId) // 通过MiddleName关联LastName父表 .join(MiddleName.self, parent: \MiddleName.$lastname) // 匹配你SQL中的非空过滤条件 .filter(\FirstName.$name != "") .filter(MiddleName.self, \.$name != "") // 组合或条件:满足姓氏为Smith 或者 中间名为James .group(.or) { conditionGroup in conditionGroup.filter(LastName.self, \.$name == "Smith") conditionGroup.filter(MiddleName.self, \.$name == "James") } // 匹配你SQL中的排序规则 .sort(LastName.self, \.$id) .sort(MiddleName.self, \.$id) .sort(\FirstName.$id) // 若需要同时返回关联的中间名、姓氏字段,添加with嵌套加载 .with(\.$middleNameId) { middleName in middleName.with(\.$lastname) } .all() .whenComplete { result in switch result { case .success(let matchedFirstNames): // 处理查询结果:matchedFirstNames就是符合条件的FirstName记录 // 可通过 matchedFirstNames[0].middleNameId.name 获取中间名 // 可通过 matchedFirstNames[0].middleNameId.lastname.name 获取姓氏 break case .failure(let error): // 处理查询错误 break } }
2. 适配你提供的原生SQL(PostgreSQL专属DISTINCT ON逻辑)
如果你需要和示例原生SQL完全一致的去重、正则匹配逻辑,Fluent也支持对应语法,代码如下:
FirstName.query(on: db) // 指定返回字段 .field(LastName.self, \.$name) .field(MiddleName.self, \.$name) .field(FirstName.self, \.$id) .field(FirstName.self, \.$name) .field(FirstName.self, \.$middleNameId) // 关联表 .join(parent: \.$middleNameId) .join(MiddleName.self, parent: \MiddleName.$lastname) // 非空过滤 .filter(\FirstName.$name != "") .filter(MiddleName.self, \.$name != "") // PostgreSQL正则匹配,对应SQL里的 ln.name ~ 'smith' .filter(LastName.self, \.$name =~ "smith") // 排序 .sort(LastName.self, \.$id) .sort(MiddleName.self, \.$id) .sort(\FirstName.$id) // 去重规则,对应SQL里的 DISTINCT ON (ln.id, mn.id) .unique(on: LastName.self, \.$id, MiddleName.self, \.$id) .all()
注意事项
- 上述
DISTINCT ON是PostgreSQL专属语法,如果你使用其他数据库,需要替换为对应数据库的去重逻辑 - 用
join(parent:)的方式关联表会自动匹配你Model中定义的外键,不需要手动写关联条件,避免拼写错误 - 多条件组合可以通过嵌套
.group(.and)/.group(.or)实现任意复杂度的且/或逻辑
内容的提问来源于stack exchange,提问作者user2616355
相关产品推荐
相关产品推荐

