CoreData - 按关系批量获取对象以获得更好的性能

Posted

技术标签:

【中文标题】CoreData - 按关系批量获取对象以获得更好的性能【英文标题】:CoreData - fetch objects by relationship in a batch for better performance 【发布时间】:2017-08-08 16:26:52 【问题描述】:

简介

只要有可能,我就会尝试在核心数据中使用查找或创建模式。当我为一组可通过 id 识别的项目执行此操作时(无论是 string 还是 int),我会分批执行此操作(因为反对对每个项目进行一次提取):

let itemIDs = Set(items.map  $0.id )
let fetchRequest = NSFetchRequest<E>(entityName: E.entityName())
fetchRequest.predicate = NSPredicate(format: "id IN %@", itemIDs)
let foundObjects = try! context.fetch(fetchRequest)

问题

我有一个无法通过 id 而是通过它与其他实体的关系来识别的实体

ItemPosition
===============
attributes:
- position
---------------
relationships:
- endpoint: N:1
- item: N:1

这里的唯一键是endpointitem 的组合。

对于这个实体,我对每个项目进行一次提取,因为我不知道如何批量进行:

var foundObjects: [ItemPosition] = []
for item in items 
   let fetchRequest = NSFetchRequest<E>(entityName: E.entityName())
        fetchRequest.predicate = NSPredicate(format: "item = %@ AND endpoint = %@", item, endpoint)
   let results = try! context.fetch(fetchRequest)
   if let position = results.first 
       foundObjects.append(position)
   

这不是最优的,因为它会针对每个项目访问 SQL 数据库,我想避免这种情况。

问题

有没有办法通过多个关系批量获取对象?类似于上面提到的NSPredicate(format: "id IN %@", itemIDs)

【问题讨论】:

是否考虑过对实体进行初始提取,然后在返回的对象数组上调用.filter?这将允许您删除您想要或不需要的对象。 【参考方案1】:

我可以想到几种方法来做到这一点,但都不是特别优雅。您可以使用复合 OR 谓词:

var predicates: [NSPredicate] = []
    for item in items 
        predicates.append(NSPredicate(format: "item = %@ AND endpoint = %@", item, endpoint))
    
    let compoundPredicate = NSCompoundPredicate.init(orPredicateWithSubpredicates: predicates)
    let results = try! context.fetch(compoundPredicate)

或者您可以通过附加端点和项目 ID 为 ItemPosition 对象生成一个 ID,然后通过它获取?

【讨论】:

以上是关于CoreData - 按关系批量获取对象以获得更好的性能的主要内容,如果未能解决你的问题,请参考以下文章

以一对多关系从 coredata 中获取所有对象

在 coredata 中获取关系对象

核心数据 - 按关系选择

从 CoreData 关系中获取错误实体的对象

CoreData:获取具有给定属性和给定关系的对象?

Core Data - 批量处理获取结果的属性