swift里的Realm对象,如何实现多表联合查询(使用RealmSwift),以实现类似于mysql的 select a.* from a,b where a.id=b.id and b.name=? 呢?
一.A
和 B
没有关系
如果 A
和 B
之间没有直接的关系,可以通过手动查询和过滤来实现联合查询。
数据模型
import RealmSwift
class A: Object { @Persisted var id: Int @Persisted var name: String // 其他字段... }
class B: Object { @Persisted var id: Int @Persisted var name: String // 其他字段... }
|
查询实现
let realm = try! Realm()
// 目标 name let targetName = "someName"
// 1. 查询 B 中符合条件的 id let bResults = realm.objects(B.self).filter("name == %@", targetName)
// 2. 提取 B 中符合条件的 id 列表 let bIds = bResults.map { $0.id }
// 3. 查询 A 中 id 在 bIds 列表中的记录 let aResults = realm.objects(A.self).filter("id IN %@", bIds)
// 输出结果 for a in aResults { print("A: \(a)") }
|
二.A
和 B
是一对一关系
如果 A
和 B
是一对一关系,可以在 A
中定义一个 B
的引用,然后直接通过关系查询。
数据模型
import RealmSwift
class B: Object { @Persisted var id: Int @Persisted var name: String // 其他字段... }
class A: Object { @Persisted var id: Int @Persisted var name: String @Persisted var b: B? // 一对一关系 // 其他字段... }
|
查询实现
let realm = try! Realm()
// 目标 name let targetName = "someName"
// 直接查询 A 中 b.name 匹配的记录 let aResults = realm.objects(A.self).filter("b.name == %@", targetName)
// 输出结果 for a in aResults { print("A: \(a)") }
|
三.A
和 B
是一对多关系(A.List< B >)
如果 A
和 B
是一对多关系,可以在 A
中定义一个 List<B>
,然后通过 ANY
关键字查询。
数据模型
import RealmSwift
class B: Object { @Persisted var id: Int @Persisted var name: String // 其他字段... }
class A: Object { @Persisted var id: Int @Persisted var name: String @Persisted var bs: List<B> // 一对多关系 // 其他字段... }
|
查询实现
let realm = try! Realm()
// 目标 name let targetName = "someName"
// 查询 A 中 bs 列表中任意一个 B 的 name 匹配的记录 let aResults = realm.objects(A.self).filter("ANY bs.name == %@", targetName)
// 输出结果 for a in aResults { print("A: \(a)") }
|
四.A
和 B
是一对多关系(B.owner=A)
如果 A
和 B
是一对多关系,但关系是通过 B
中的 owner
字段(即反向关系)来维护的,而不是在 A
中使用 List<B>
,那么可以通过 LinkingObjects
来实现查询。
数据模型
在这种情况下,B
中会有一个指向 A
的 owner
字段,而 A
中不需要显式定义 List<B>
。Realm 会自动通过 LinkingObjects
提供反向关系。
import RealmSwift
class A: Object { @Persisted var id: Int @Persisted var name: String // 不需要显式定义 List<B> }
class B: Object { @Persisted var id: Int @Persisted var name: String @Persisted var owner: A? // 指向 A 的引用 // 其他字段... }
|
查询实现
let realm = try! Realm()
// 目标 name let targetName = "someName"
// 1. 查询 B 中 name 匹配的记录 let bResults = realm.objects(B.self).filter("name == %@", targetName)
// 2. 提取 B 中符合条件的 owner(A 的引用) let aResults = bResults.compactMap { $0.owner }
// 输出结果 for a in aResults { print("A: \(a)") }
|
一对多优化:使用 LinkingObjects
实现反向查询
如果你希望在 A
中通过反向关系(LinkingObjects
)直接访问关联的 B
对象,可以在 A
中定义 LinkingObjects
。
修改数据模型
import RealmSwift
class A: Object { @Persisted var id: Int @Persisted var name: String // 定义反向关系 let bs = LinkingObjects(fromType: B.self, property: "owner") }
class B: Object { @Persisted var id: Int @Persisted var name: String @Persisted var owner: A? // 指向 A 的引用 // 其他字段... }
|
查询实现
通过 LinkingObjects
,你可以直接查询 A
中关联的 B
对象。
let realm = try! Realm()
// 目标 name let targetName = "someName"
// 查询 A 中 bs 列表中任意一个 B 的 name 匹配的记录 let aResults = realm.objects(A.self).filter("ANY bs.name == %@", targetName)
// 输出结果 for a in aResults { print("A: \(a)") }
|