Swift NSPredicate SUBQUERY with NOT IN?

Posted

技术标签:

【中文标题】Swift NSPredicate SUBQUERY with NOT IN?【英文标题】:Swift NSPredicate SUBQUERY with NOT IN? 【发布时间】:2019-10-04 13:18:17 【问题描述】:

是否可以在带有 SUBQUERY 的 NSPredicate 中使用“NOT IN”?

在“正常”的 NSPredicate 中,这是有效的:

NSPredicate(format: "NOT (uid IN %@)", uids)

但是,我正在使用 SUBQUERY 在 NSPredicate 中尝试这种“NOT IN”语法,但它不起作用(但也不会崩溃):

NSPredicate(format:"SUBQUERY(forests.treeFamily, $tree, NOT ($tree._id IN %@)) .@count > 0", arrayOfTreesIds)

虽然以下“IN”语法可以正常工作:

NSPredicate(format:"SUBQUERY(forests.treeFamily, $tree, $tree._id IN %@) .@count > 0", arrayOfTreesIds)

知道如何实现这一目标吗?


更新

Jay 的回答让我觉得我对架构/类不够清楚。

让我们以狗为例。

我们有一个 ShelterClass,它具有 Dogs 的属性。它是一组 Dog 对象,用于跟踪收容所中托管的狗。

Dog 类有一个“race”属性,它是对 Race 类的引用。

我想过滤没有某些狗种族的收容所。 虽然我会用它来过滤确实有某些狗种族的收容所:

NSPredicate(format:"SUBQUERY(dogs.race, $race, $race._id IN %@) .@count > 0", arrayOfRaceIds)

我找不到如何过滤掉/使用“NOT IN”语法。

【问题讨论】:

感谢您的澄清。如果我没看错,请查看我的更新答案。 【参考方案1】:

超级简单!这是常规过滤器的格式

如果你有一个 DogClass

class DogClass: Object 
   @objc dynamic var name = ""

然后想要一个不叫 Dino 和 Fido 的狗的列表,这里是代码

 let dogNames = ["Fido", "Dino"]
 let results = realm.objects(DogClass.self).filter("NOT dog_name IN %@", dogNames)

子查询的结果将取决于您期望的结果以及子查询的用途。

例如,假设我们有一个具有狗属性的 PersonClass,它是他们认识的狗的列表。如果我们想要所有不认识 Fido 或 Dino 的人,这就是查询

let personResults = realm.objects(PersonClass.self).filter("NOT ANY dogs.dog_name in %@", dogNames)

编辑

根据更新的问题,让我们试试这个。由于我在上面使用了 PersonClass,所以我会提出这个问题。

我想要一份没有品种(种族)的所有人(庇护所)的列表 猎犬。这是用于跟踪品种的 Breed 类

class BreedClass: Object 
    @objc dynamic var breed = ""

以及具有品种属性的 DogClass(如问题中的“种族”)

class DogClass: Object 
    @objc dynamic var dog_id = NSUUID().uuidString
    @objc dynamic var dog_name = ""
    @objc dynamic var dog_breed: BreedClass?

    override static func primaryKey() -> String? 
        return "dog_id"
    

最后是拥有 DogClass 对象列表的 Person 类

class PersonClass: Object 
    @objc dynamic var person_id = UUID().uuidString
    @objc dynamic var first_name = ""

    let dogs = List<DogClass>()

    override static func primaryKey() -> String? 
        return "person_id"
    

然后我们有一些填充的品种对象

let b0 = BreedClass()
b0.breed = "Mut"

let b1 = BreedClass()
b1.breed = "Poodle"

let b2 = BreedClass()
b2.breed = "Hound"

然后将品种添加到狗并将狗添加到人。在这种情况下,我们只会养一只 b2 狗,猎犬

let d2 = DogClass()
d2.dog_name = "Sasha"
d2.dog_breed = b2

在这种情况下,我添加了 4 个人,Bert、Ernie、Grover 和 The Count。 Ernie 是我添加猎犬的唯一人。

最后一个查询将返回所有没有猎犬品种的人。

let breed = "Hound"
let personResults = realm.objects(PersonClass.self).filter("NOT ANY dogs.dog_breed.breed == %@", breed)
for person in personResults 
    print(person.first_name)

和输出

Bert
Grover
The Count

厄尼失踪了,因为他有一只猎犬。

【讨论】:

嗨,杰!感谢您的回答。我更新了我的问题,以更清楚地了解预期结果、类/模式以及对象嵌套更深的事实。 太棒了 - 我不知道你可以像这样潜得更深。谢谢@Jay!我还没有对此进行测试,但我很快就会测试。 工作!因为我不仅要排除一个品种,而且要排除几个品种,并通过一系列品种,我用IN %@替换了== %@

以上是关于Swift NSPredicate SUBQUERY with NOT IN?的主要内容,如果未能解决你的问题,请参考以下文章

swift 3 迁移后 NSPredicate 崩溃

swift - NSPREDICATE 失败 [重复]

Swift3 中的 NSPredicate

Swift NSPredicate SUBQUERY with NOT IN?

swift : 使用 NSPredicate 过滤 NSMutableDictionary 的 NSMutableArray

Swift 3 NSPredicate 关系请求返回空数组