复杂的NSPredicate遍历多个实体和关系类型

时间:2011-08-22 20:18:23

标签: objective-c ios core-data nspredicate key-value-observing

由于数据库结构有点复杂,我很难解决这个谓词问题。我有以下数据库结构,或者至少是这个问题的关注点:

出版者<< --->> PUBLICIST<< - BOOK<< ---> AUTHOR<< - >> AGENTS

我尝试了以下谓词,当我过去遍历关系时,我已经使用过,但不是这个程度。我应该提一下,我有一个带代理名称的NSArray,我想查询数据库,以确定代理使用的出版社列表:

NSArray *agentNames = [NSArray arrayWithObjects:Dan, Hunter, Sloan, Jackson];

NSFetchRequest *request = [[NSFetchRequest alloc] init];

request.entity = [NSEntityDescription entityForName:@"Publisher" inManagedObjectContext:context];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor
             sortDescriptorWithKey:@"publisherName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] ];
request.predicate = [NSPredicate predicateWithFormat:@"ANY pubHouse.publicist.assignedBook.authorRep.agentName IN %@", [agentNames valueForKey:@"agentName"]];
request.fetchBatchSize = 20;

    NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];

当我运行上一个谓词时,我收到以下警告:

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unimplemented SQL generation for predicate : ANY pubHouse.publicist.assignedBook.authorRep.agentName IN

我认为当我将图书实体关系转移到作者实体然后转移到代理实体时,谓词就会中断。在这一点上,建议会有所帮助。感谢

3 个答案:

答案 0 :(得分:6)

您的问题是谓词解析器不知道应该应用哪个集合ANY

使用此数据模型:

PUBLISHER<< --- >>PUBLICIST<<-->BOOK<<--->AUTHOR<<-->>AGENTS

...你的密钥路径:

pubHouse.publicist.assignedBook.authorRep.agentName

...在对象和关系集方面看起来像:

object.set.object.object.set

所以,这是ANY可以适用的两套。

你可以尝试构建一个子查询来处理谓词,但是如果你必须横穿那么多关系,那么你的fetch将涉及很大一部分数据并且会非常非常慢(假设你在第一个工作中使用它)地方。)

通常当你最终得到这样一个错综复杂的谓词时,它表明你正在从错误的一端接近问题。在这种情况下,从一个简单的谓词开始会更容易:

NSArray *agentNames = [NSArray arrayWithObjects:Dan, Hunter, Sloan, Jackson];
request.entity = [NSEntityDescription entityForName:@"Agent" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:@"agentName IN %@", agentNames];

然后你会走关系的关键路径:

authors.books.publicist.publishers 

...找到所有相关的发布商。

我认为无论你做什么都会遇到麻烦,因为有多个多对多的关系,例如

PUBLISHER<<--->>PUBLICIST

...以指数方式增加谓词和关系的复杂性。通常,在这种情况下,您可能需要一个额外的实体来更彻底地建模其中一个关系。这通常会降低数据模型本身的复杂性,从而简化了提取和行走。

答案 1 :(得分:0)

NSArrayvalueForKey:可能存在问题。我见过一个使用NSCompoundPredicate的循环中添加数组项的解决方案。

顺便说一下,在你的多重关系链中,你是不是想念你的作者

答案 2 :(得分:-1)

将谓词字符串的IN子句包装在括号中:

@"ANY (pubHouse.publicist.assignedBook.authorRep.agentName IN %@)"

很高兴知道它是否有效。