排序和过滤核心数据关系的更有效方法是啥?

Posted

技术标签:

【中文标题】排序和过滤核心数据关系的更有效方法是啥?【英文标题】:What is the more efficient way of sorting and filtering Core Data relationships?排序和过滤核心数据关系的更有效方法是什么? 【发布时间】:2013-01-07 05:16:22 【问题描述】:

假设我有一个 Podcast 实体,它有很多集,我很困惑其中哪一个是剔除和排序的首选选项:

// Always work with the relationship property
- (NSSet*)unfinishedEpisodes 
  NSArray* episodes = self.episodes.allObjects;

  NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(PodcastEpisode* episode, NSDictionary* bindings) 
    return !episode.isFinished;
  ];

  NSArray* unfinishedEpisodes = [episodes filteredArrayUsingPredicate:predicate];

  return [NSSet setWithArray:unfinishedEpisodes];


- (NSArray*)unfinishedEpisodesSortedByAge 
  NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];

  return [self.unfinishedEpisodes.allObjects sortedArrayUsingDescriptors:sortDescriptors];

// Fetch specific sets of data as needed
- (NSArray*)unfinishedEpisodes:(NSArray*)sortDescriptors   
  NSFetchRequest* fetch = [[NSFetchRequest alloc] initWithEntityName:@"Episode"];

  NSPredicate* predicate = [NSPredicate predicateWithFormat:@"podcast == %@ AND playcount == 0", self];
  fetch.predicate = predicate;

  fetch.sortDescriptors = sortDescriptors;

  NSArray* results = [KRTDataManager.sharedManager.mainObjectContext executeFetchRequest:fetch error:nil];

  return results;


- (NSArray*)unfinishedEpisodesSortedByAge 
  NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES];

  return [self unfinishedEpisodes:@[ sortDescriptor ]];

在 SQL 中尽可能多地做的那部分人很难认为选项 1 更好,但我读过的大部分内容似乎表明,一旦播客使用 (NSSet*) 剧集非常便宜对象出现。我对在这些情况下如何处理核心数据故障的理解非常不稳定,我意识到核心数据不应该真正与 SQL 数据库进行比较。不过,仅基于这两个选项的构造方式,我认为将谓词和排序描述符直接烘焙到 fetch 中会有一些好处;但也许这不足以弥补关系所提供的收益。

谢谢。

【问题讨论】:

【参考方案1】:

第一个代码在处理大型结果集时效率低下,因为它在内存对象中运行。所有对象都必须加载到内存中,因此如果它们不存在,它们将在引发故障时一个接一个加载。

第二个代码将在 sql 端执行所有操作,并为您提供已过滤和排序的结果。 CoreData 还使用内部缓存来优化此类查询,因此如果剧集尚未在其他地方加载,我更喜欢此选项。启用 CoreData 调试以查看 sql 查询的外观。 There is already an answer how to do that.

【讨论】:

+1。选项 2 几乎可以肯定是最好的方法。您还可以对结果应用批处理,或者使用NSFetchedResultsController 来管理播客的任何显示。目前,我选择的播放器中有大约 1000 多个未播放的播客,所以除非你知道你总是要处理小数字,否则选项 2 是最好的。 好的,所以扩展一下。假设我有一个所有未完成剧集的表格视图,按年龄排序,按 Podcast 分组。在这种情况下,假设您正在检查每个部分中的单元格的 [thePodcast unfinishedEpisodesSortedByAge],每次调用都进行核心数据获取会更好吗?或者,如果 [Episode allUnfinishedEpisodes] 仅加载一次(隐式或显式)并且将其过滤到仅接收者的剧集在代码中完成会更好吗? @farski 在 UITableView 中你绝对应该使用 NSFetchedResultController,所以你需要使用 NSPredicate 过滤记录。与 NSFetchedResultController 一起使用的 UITableView 将使用批量查询 (setBatchSize:),应用程序将更加高​​效并且消耗更少的内存。在 tableviews 中使用部分时,请记住不要使用动态属性(部分应预先存储在核心数据中)。

以上是关于排序和过滤核心数据关系的更有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 3 实现短路(单个数据多次)和过滤核心数据的最佳方法是啥?

LINQ - 按相同功能过滤和排序的最有效方法

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

在一对多关系中使用 NSPredicate 进行过滤

排序和过滤

使用 NSPredicate 过滤核心数据中的对象