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

Posted

技术标签:

【中文标题】用于多对多关系的 NSPredicate 过滤器【英文标题】:NSPredicate filter for many-to-many-to-many relationships 【发布时间】:2011-09-29 04:40:08 【问题描述】:

我对使用 NSPredicate 还很陌生,但我遇到了一个有点复杂的问题,我不太确定解决方案的最佳方法。

我正在尝试为一个名为 Instrument 的实体构建一个过滤器,它可以与许多程序一起使用。反过来,程序与一种或多种疾病有关。疾病与许多程序有关,仪器可用于多个程序。换句话说,我有以下多对多的关系:

Instruments <-> Procedures <-> Diseases

我想做的是使用 Disease.title 过滤仪器。在一个简单而神奇的世界里,这就像

//where predicate is used on the Instruments array
[NSPredicate predicateWithFormat:@"(procedures.diseases.title == %@)", diseaseTitleString];

逐段浏览(有一些错别字和命名错误),我发现过滤器知道Procedures和Diseases的字段足以告诉我“diseaseTypes”不是procedures上的字段,而“name”是不是疾病领域。天真让我希望这个简单的谓词能奏效。

我什么也得不到。

我也尝试过使用(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】:

在上面的谓词中,将双等号替换为单等号。还要添加一个“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]]; 然后我做了一个与其他过滤器一起工作的复合。我还有什么遗漏吗? 如果在没有 and 复合的情况下运行它会发生什么? 仅使用该谓词(无复合词)运行过滤器仍然不会返回任何内容。 :( 嗯。你能打开 .sqlite 文件并运行等效的 SQL 查询吗?剪切并粘贴疾病标题。另外,确认没有尾随空格等。 @MaxMacLeod 嗨,Max,很好的答案,也许你能帮帮我。我的关系 Object>addresses>phones 我需要检查 phones.tel 是否包含我的电话号码,我尝试 [NSPredicate predicateWithFormat:@"ANY addresses.phones.tel = %@", searchWord] 但我收到错误 @ 987654327@,你能给点建议吗?谢谢!

以上是关于用于多对多关系的 NSPredicate 过滤器的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 在核心数据中的多对多关系

用于多对多关系的 NSPredicate

NSPredicate 用于多对多关系

核心数据:过滤多对可能与 NSPredicate 的关系

如何为 CoreData 多对多关系编写 NSPredicate

具有多对多关系的核心数据 NSPredicate