按祖父母实体关系过滤核心数据

Posted

技术标签:

【中文标题】按祖父母实体关系过滤核心数据【英文标题】:Core Data filter by grandparent entity relationship 【发布时间】:2016-04-06 13:48:30 【问题描述】:

我有三个这样的实体: 出版商 > 作者 > 书籍

Publisher
    id = <uniqueId>
    authors -->> Author

Author
    id = <uniqueId>
    books -->> Book //ordered relationship
    publisher --> Publisher

Book
    info = <string_with_info>
    author --> Author

我想按 Author id 和 Publisher id 过滤所有书籍并获取它们的 info 属性。类似于:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"author.publisher.id == %@ AND author.id == %@", publisherId, authorId];
[request setPredicate:predicate];
[request setEntity:[NSEntityDescription entityForName:@"Book" inManagedObjectContext:managedContext]];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch:@[@"info"]];


 NSError *error = nil;
 NSArray *results = [managedContext executeFetchRequest:request error:&error];

其中结果应该包含许多带有书籍信息的字符串。 我不确定author.publisher.id == %@ 部分是否有效。

我可以获取作者,然后获取带有书籍实体的 MutableSet。从那里我可以遍历它们并将它们的信息推送到一个新数组。这可以完成这项工作,但如果可能的话,我想只用一个 fetch 来做同样的事情。


编辑:一个可行的解决方案是像这样改变谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(0 != SUBQUERY(author, $x, (0 != SUBQUERY($x.publisher, $y, $y.id like %@).@count)).@count) AND author.id  like %@ ", publisherId, authorId];

一些澄清。作者 ID 与发布者相关联,并且仅对该发布者唯一。您可以有两个作者具有相同的 id 但具有不同的出版商。

扩展原始问题。作者书籍已订购。 results 中的信息的排序顺序是否与作者中书籍的排序顺序相同?根据我的有限测试,答案是肯定的。

Mundi 已指出可能的 id 冲突,并已记录。

【问题讨论】:

【参考方案1】:

首先,在澄清您的 authorID 不是唯一之后,您需要使用您原来的复合谓词:

NSPredicate(format: "author.publisher = %@ && author.authorID = %@",
  publisher, authorID)

顺便说一句,我会将您的属性“id”替换为其他内容,因为与“id”存在一些潜在的名称冲突。

但是只能获取作者,使得谓词更简洁:

NSPredicate(format: "publisher = %@ && authorID = %@", publisher, authorID)

其次,books 已经是一个集合,所以不需要得到不同的结果。实际上,如果您有作者对象,您可以在没有显式获取的情况下执行此操作。

author.books.map  $0.info 

就是你所需要的。看看 Swift 是多么优雅!

【讨论】:

作者 ID 与发布者相关联。可能有第二个出版商,其作者与另一个出版商的另一个作者具有相同的 id。在问题中没有正确解释是我的错误。感谢您指出可能的 id 冲突。会解决的。 那么逻辑仍然成立。 Core Data 并不关心这些作者 ID 是什么——框架通过关系维护自己的 ID。 恐怕我听不懂。您不是在过滤所有可以说 authorID = 1 的书籍。我们在两个出版商中有这样的 authorID。因此,您的谓词获得 PublisherOne->AuthorOne,authorID = 1->books 和 PublisherTwo->AuthorTwo,authorID = 1->books。现在你有了两个作者的书的结果。 您的 authorID 不是唯一的。因此,它们不是主键,也不会在其他表中用作外键。它们只是一些属性。让关系管理这些细节——这就是 Core Data 的用途。我将更改谓词以反映这一点。 好的,我相信我现在理解你了。但是我确实想使用它们以及 profileID 来过滤。谢谢你的解释。

以上是关于按祖父母实体关系过滤核心数据的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate 按属性过滤核心数据关系 NSSet

如何按不相关的实体过滤核心数据

在 Core Data 中获取过滤的关系

对许多实体和实体关系进行过滤的核心数据提取

如何创建一个基于父关系过滤核心数据对象的 NSFetchRequest?

核心数据。按日期过滤