核心数据,尝试使用NSPredicate过滤一个toMany关系集合,但是出现了“此处不允许使用to-many键”错误。

6
这是我的模型: http://www.girardet.ch/model.png 我的目标是按照以下条件检索所有引语:
  • 属于特定主题:Themes的name_en属性
  • 按相关性排序
  • 通过作者过滤(使用Authors的alias属性)
这是我的代码:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ThemeEntries" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"relevancy" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

// predictate - filter
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"theme.name_en=%@ AND quotes.author.alias=%@",@"mytheme", @"myauthor"];

[fetchRequest setPredicate:predicate];

我设置谓词时出现了“此处不允许使用to-many键”错误。

如果我改用以下谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"theme.name_en=%@, @"mytheme"];

它的功能很好,我可以循环遍历得到的ThemeEntries并获取所有的引用。但是它没有按作者进行过滤。

我该怎么做才能按作者过滤呢?

1个回答

26

你的问题在于一个关键路径的关系是多对多,并且谓词不知道哪个特定的对象与哪个相关联。

你有一个ThemeEntities<<-->>Quotes,它在每一端都产生一个集合。 quotes.author.alias关键路径表示“一组引用实例,每个实例都链接到作者实例,而作者实例反过来具有别名属性”。 谓词无法处理集合。

您需要使用子查询来跳过一个多对多的关键路径。 子查询本质上是一个嵌套的谓词,它搜索一组并返回与嵌套谓词匹配的另一组对象。 子查询文档不完善,但它们具有以下形式:

SUBQUERY(collectionName,$collectionElementVariable,expression-with-$collectionElementVariable)
在这种情况下,您正在寻找具有与所提供的字符串匹配的别名关系的任何报价实例。您的谓词应该如下所示:
@"theme.name_en=%@ AND (0!=SUBQUERY(quotes,$eachQuote,$eachQuote.author.alias=%@).@count)",@"mytheme", @"myauthor"

子查询表示:对于报价集合中的每个报价对象,请测试其作者关系对象是否具有与“myauthor”匹配的别名属性。计算具有该匹配项的报价对象的数量。如果数量为非零,则返回 TRUE。

当您跨越一对多的关系路径时,需要使用子查询。


非常感谢您提供这个好答案。我之前不知道子查询,这对我确实非常有帮助。但在我的情况下,我想要过滤请求中“所有”ThemeEntries返回的报价集。使用子查询可以过滤返回的条目,确保它们通过相关的报价与作者建立关系。最终我做的是获取与主题相关的所有报价而不过滤作者,并在之后进行过滤。但我仍然想知道是否有一种直接在请求中完成它的方法(就像SQL中的左连接一样)。 - Ben
我不确定你在寻找什么,但上述谓词只搜索与特定ThemeEntities实例相关联的那些“Quote”实例。事实上,由于谓词的评估方式,它只会检查通过第一个测试的ThemeEntities的“Quote”实例。 - TechZen
感谢 @TechZen 解决了这个问题!!!我为此苦苦挣扎了数小时,试图找出一种方法来创建一个复合谓词,使用两个条件对同一集合元素应用过滤器。有了你的答案,这变得非常容易。谢谢! - Greg Combs

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