针对不同对象的多个领域查询
Posted
技术标签:
【中文标题】针对不同对象的多个领域查询【英文标题】:Multiple Realm queries for different Objects 【发布时间】:2018-07-23 09:05:24 【问题描述】:我想创建一个返回Results<A>
类型对象的整个数据库搜索。我有一个类A
继承自领域Object
,然后还有许多其他类继承自该子类。像这样的:
class A: Object
protocol Z
class B: A, Z
class C: A, Z
class D: A, Z
...
现在我想同时查询不同的类,我正在做这样的事情:
private func getResults<T: A>(withTypes types: [T.Type])
for type in types
let foundIds = getRealm().objects(type).filter(aPredicate)
ids.append(contentsOf: foundIds)
// Do something with all those ids
我这样称呼它:
getResults(withTypes: [B.self, C.self, D.self])
问题是 Realm 不喜欢多态性,一旦我在调用函数时在数组中添加多个类类型,它就会崩溃,因为数组的推断类型是 A.self
而不是每个中的单个元素数组的位置。过滤是通过使用A
不符合的Z
协议变量完成的 - 它不应该符合 - 但对象的其余部分确实符合它。所以这行得通:
getResults(withTypes: [C.self])
或者这个:
getResults(withTypes: [D.self])
因为Array
的推断类型是C.self
或D.self
,而不是推断的通用A.self
。
我想指出,在数据库中没有任何A
对象,它只是所有其他对象的超类。
如何创建多重搜索?
我认为我可以创建一种可搜索的对象并对其进行查询,但我管理的数据库很大,我不知道这是否会对系统的性能产生重大影响。
提前致谢!
【问题讨论】:
【参考方案1】:在您的查询中,如果您只对获取 id 并将它们附加到数组感兴趣,您可以将它们映射到 ids.append(contentsOf: foundIds.map( $0.idFromZProtocol ))
。但这会禁用 Realm 的延迟加载,因为所有对象都会被访问。
你也可以做其他方式:
假设 A 是动物,B 是狗,C 是鸟,D 是猫。 您正在寻找所有的绿色动物。你可以拥有
Animal
@objc dynamic var dog: Dog?
@objc dynamic var bird: Bird?
@objc dynamic var cat: Cat?
Bird, Cat, Dog
@objc dynamic var color: String
@objc dynamic var legNumber: Int
let predicate = "dog.color == Green || bird.color == Green || cat.color == Green"
getRealm().objects(Animal.self).filter(predicate)
您可以在 Animal 上处理一个变量,通过检查哪个变量不是 nil 来判断它是猫、狗还是鸟。您还可以将 Z 协议分配给 Dog、Cat 和 Bird 以执行 Animal.color
而不是猜测 Animal.dog?.color
或 Animal.cat?.color
等
通过这种方法,您可以保留 Realm 的延迟加载功能,如果您有一个非常大的 Realm 文件,这非常好。
【讨论】:
不幸的是,这不是一个最佳解决方案,因为我有 50 多个不同的A
子类,正如我所说,A
没有存储在数据库中。因此,即使我认为 A
-dirty 中有该结构,我也无法搜索该特定对象,因为它不存在。如果我必须存储A
才能做到这一点,我可以创建一个Search
实体用于搜索,该实体将包含我想要搜索的领域对象的id
。所以我会存储一个新对象Search
而不是A
,并且我会避免在A
中创建所有这些变量。
哦,我错过了 A 不在 DB 中的那部分。那么在这种情况下,这是不可能的。您需要通过执行类似于我建议的操作(例如 CPU 高效)来重新考虑您的数据库架构。它可能很脏,这就是为什么你需要创建一个顶层来清理它并且只使用那个顶层。或者您必须通过手动获取所有对象并手动合并来完成所有处理。它不能是 Result(它是直接映射到 Realm DB,所以 A 需要在那里),但将是一个满载的 Array。
是的,我明白了......也许最好的方法就是你所说的。将A
保存到数据库并使其扩展协议并避免在A
中创建所有这些变量。
你总是可以选择 SQLite,它可能更符合你在模式方面的需求。
我们已经有了一个非常大的产品,并且改变它会花费我们很多钱,我们不能浪费在这上面......但是感谢您的帮助:)以上是关于针对不同对象的多个领域查询的主要内容,如果未能解决你的问题,请参考以下文章