2011-08-22 66 views
0

由于数据库结构有点复杂,我很难解决这个谓词问题。我有以下的数据库结构,或者至少是值得关注的一个问题:复杂的NSPredicate遍历多个实体和关系类型

PUBLISHER < < --- >>公关< < --BOOK < < --->作者< < - >>代理

我试过以下谓词,当我遍历过去的关系时使用过,但没有达到这个程度。我要指出,我有一个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 

我相信,当我将书实体关系传送到作者实体,然后到达代理实体时谓词会中断。在这一点上,建议会有所帮助。由于

+0

你的NSArray agentNames中有哪些变量? NSManagedObject的子类?字典? – Mundi

+0

您的实体之间的所有关系是否只是定期的旧关系,或者是关于它们的任何“特别”?另外,'authorRep.agentName'看起来有点好奇。 'agentName'真的是你作者代理关系的名字吗?还是你的意思是像'authorRep.agent.agentName'? –

+0

这是从前一个视图控制器传递的一个Agent对象数组,用户可以选择他们想要查询的代理。我以前用这种方法取得了成功。我在这个问题中以这样一种方式显示了示例数组,以帮助那里的优秀的撒玛利亚人明白我想要完成的事情。感谢您付出的努力。 – dman

回答

6

你的问题是,谓词解析器不知道应该应用什么设置ANY

有了这个数据模型:

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

...您的keyPath:

pubHouse.publicist.assignedBook.authorRep.agentName 

...是以对象的形式,并设置的关系看起来像:

object.set.object.object.set 

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

你可以尝试建立一个子查询来处理谓词,但是如果你必须横切那么多的关系,你的获取会涉及大量的数据,并且会非常非常缓慢(假设你能够在第一个地方)。

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

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

然后你会走关系的keyPath:

authors.books.publicist.publishers 

...找到所有相关的出版商。

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

PUBLISHER<<--->>PUBLICIST 

...增加了谓词和关系呈指数级走向的复杂性。通常,在这种情况下,您可能需要额外的实体来更深入地模拟其中一种关系。这通常会降低数据模型本身的复杂性,从而简化了抓取和漫游。

+0

你说得对。我试图找到一个体面的解决方法,但我必须消除一些关系,并创建实体,以减少多对多关系的数量,以便通过关系。谢谢您的帮助 – dman

-1

只是包装你的谓语字符串的IN子句中括号:

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

会很高兴知道,如果它的工作原理。

+0

-1不行,那不行。 –

0

也许NSArrayvalueForKey:有问题。我见过一个解决方案,它使用NSCompoundPredicate在循环中添加数组项。

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

+0

'valueForKey:'适用于'NSArray'。它构造一个新的数组,其中包含调用'valueForKey:'的结果和数组中每个元素的给定键(用'NSNull'替换nil值)。 –

+0

@KevinBallard请参阅我上面的内容。 – Mundi

+0

来自'[agentNames valueForKey:@“agentName”]'的任何问题都会产生完全不同的错误。 –