NSPredicate用于多对多对多关系的过滤

3

我对使用NSPredicate还比较新,但我遇到了一个相当复杂的问题,我不确定最好的解决方法。

我正在尝试为名为Instrument的实体构建过滤器,该实体可以与许多Procedures一起使用。 Procedures反过来又与一种或多种疾病相关联。 疾病与许多Procedures相关联,并且Instrument可以在多个Procedure中使用。 换句话说,我拥有以下多对多对多关系:

Instruments <-> Procedures <-> Diseases

我希望能够通过Disease.title筛选出乐器。在一个简单而神奇的世界里,这只需要以下代码即可:
//where predicate is used on the Instruments array
[NSPredicate predicateWithFormat:@"(procedures.diseases.title == %@)", diseaseTitleString];

逐步解释这一部分(带有少量错别字和误命名),我发现过滤器了解 Procedures 和 Diseases 的字段,足以告诉我 "diseaseTypes" 不是 procedures 上的字段,"name" 不是 diseases 上的字段。天真让我希望这个简单的谓词会起作用。
但我什么也得不到。
我还尝试使用 (ALL procedures.diseases.title == %@),但那也行不通。
我看到过一些关于子谓词的东西,但没有什么真正引起我的注意或让我感到有意义。
基本上,我想要获取列表:
NSArray *instruments = [[NSArray alloc] init];
for (Disease *disease in Diseases) {
  if ([disease.title isEqualToString:titleString]) {
    for (Procedure *procedure in disease.procedures) {
      for (Instrument *instrument in procedure.instruments) {
        if (![instruments containsObject:instrument]) {
          [instruments addObject:instrument];
        }
      }
    }
  }
}

目前,我正在使用这种方法获取一个数组,可以基于其他谓词进行过滤,它可以正常工作,但看起来很丑,我感觉有更好、更干净的方式来过滤这个数组。 有人能帮助我了解NSPredicate设计的更细致用法吗?

1个回答

2

在您上面的谓词中,将双等号替换为单等号。还要添加一个“ANY”子句。最后,删除括号。因此,您将拥有:

[NSPredicate predicateWithFormat:@"ANY procedures.diseases.title = %@", diseaseTitleString];

通常,我发现处理复杂谓词的好方法是使用子谓词逐步构建它们。
因此,您可以从以下内容开始:
        NSMutableArray *subpredicates = [NSMutableArray array];

然后,逐步添加子谓词:
[subpredicates addObject:
    [NSPredicate predicateWithFormat:@"ANY procedures.diseases.title = %@",
         diseaseTitleString]]

[subpredicates addObject:anotherPredicate etc];

最后,创建您的“and”或“or”谓词,例如:
 NSPredicate *andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];

这里有一些好的提示,但是那个谓词仍然返回一个空数组。我的其他子谓词工作正常,但是这个多对多的谓词仍然不起作用,但应该等同于上面代码中构建的循环集合。[instrumentFilters addObject:[NSPredicate predicateWithFormat:@"ANY procedures.diseases.title = %@", filterValue]]; 然后我进行了一个与操作,它与其他过滤器一起正常工作。我还漏掉了什么吗? - Josh Kovach
如果您在没有使用“and”连接符的情况下运行它,会发生什么? - Max MacLeod
仅使用该谓词(无复合)运行过滤器仍然返回空值。 :( - Josh Kovach
嗯,你能打开 .sqlite 文件并运行相应的 SQL 查询吗?剪切并粘贴疾病标题。同时,请确认没有尾随空格等问题。 - Max MacLeod
有点晚了,但将 andPredicateWithSubpredicates 更改为 orPredicateWithSubpredicates 对我起作用了。 - Allen
1
@MaxMacLeod 你好Max,非常棒的回答。也许你可以帮助我。我的关系是Object<->>addresses<->>phones。我需要检查phones.tel是否包含我的电话号码。我尝试使用[NSPredicate predicateWithFormat:@"ANY addresses.phones.tel = %@", searchWord],但是我得到了错误信息“** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'multiple to-many keys not allowed here'” 你能给点建议吗?谢谢! - Roman Simenok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接