2016-08-10 42 views
2

我有一个CoreData数据库,其中包含大约500.000个邮票和86.000系列。我必须从使用JSON的web API下载它们。将核心数据加入邮票和系列没有任何问题。但是在两者之间建立关系时我遇到了麻烦。将大数据集导入核心数据,在Swift中建立关系

My datamodel 每张邮票有一个系列,每个系列可以有多个邮票。正如上面我的数据模型的图片所示。

我需要使两者之间的关系高效快速。

建立 新导入的对象之间的关系时,类似的问题经常发生:当我在做一些研究,我碰到这个网站https://www.objc.io/issues/4-core-data/importing-large-data-sets-into-core-data/我最感兴趣的部分跌跌撞撞。使用获取请求独立获取每个相关对象是非常低效的。有两种可能的解决方法:要么我们先解决类似 的批处理与我们如何首先导入对象的关系,要么缓存已导入对象的对象标识 。通过解析 批处理中的关系,我们可以大大减少一次获取许多相关对象所需的提取请求数量 。不要担心 可能长时间谓词,如:

[NSPredicate predicateWithFormat:@"identifier IN %@", identifiersOfRelatedObjects]; 

解决谓语用在IN(...)许多标识符子句 总是这样比去磁盘更高效各自独立地反对 。但是,还有一种方法可以避免获取请求 (至少如果您只需要在新导入的对象之间建立关系 )。如果缓存所有导入对象(在大多数情况下不是很多数据)中的对象ID,则可以稍后使用它们使用 objectWithID:来检索相关对象的错误。

// after a batch of objects has been imported and saved 
for (MyManagedObject *object in importedObjects) { 
    objectIDCache[object.identifier] = object.objectID; 
} 

// ... later during resolving relationships 
NSManagedObjectID objectID = objectIDCache[object.foreignKey]; 
MyManagedObject *relatedObject = [context objectWithID:objectId]; 
object.toOneRelation = relatedObject; 

注意,这个例子假定标识符属性是所有实体类型独特 ,否则我们将不得不考虑针对不同类型的,我们缓存 对象ID的方式 重复的标识符。

但我不知道他们是什么意思,有人可以给一些更多的解释。最好在Swift中,因为这是我理解最好的语言,也是我创建我的应用程序的语言。 当然其他建议也很好。 注意,离开CoreData不再是一种选择。

回答

1

在两个对象之间建立关系的任务涉及到这两个对象。考虑到它们已经在核心数据中创建,您可以使用谓词执行提取请求,如

@"countryID == %@", countryObjectData[@"id"] 

您将得到它们。但是,如果您需要建立五万个关系,则必须执行一百万次获取请求。这很慢。

检索NSManagedObjectNSManagedObjectID明显比通过属性值进行搜索要快。在开始解析之前,您可以按照server key -> objectID对的形式按实体构建所有核心数据对象的缓存。

self.cache = [NSMutableDictionary dictionaryWithCapacity:self.managedObjectModel.entities.count]; 

NSExpressionDescription *objectIdDescription = [[NSExpressionDescription alloc] init]; 
objectIdDescription.name = @"objectID"; 
objectIdDescription.expression = [NSExpression expressionForEvaluatedObject]; 
objectIdDescription.expressionResultType = NSObjectIDAttributeType; 

NSString *key = @"serverID"; 

for (NSEntityDescription *entity in self.managedObjectModel.entities) { 
    NSMutableDictionary *entityCache = [NSMutableDictionary dictionary]; 
    self.cache[entity.name] = entityCache; 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity.name]; 
    request.resultType = NSDictionaryResultType; 
    request.propertiesToFetch = @[key, objectIdDescription]; 
    NSArray *result = [self.context executeFetchRequest:request error:nil]; 

    for (NSDictionary *item in result) { 
     id value = item[key]; 
     NSManagedObjectID *objectID = item[@"objectID"]; 
     entityCache[value] = objectID; 
    } 
} 

有了这样的高速缓存,你可以得到你的对象是这样的:

id serverKey = countryObjectData[@"id"]; 
NSManagedObjectID *objectID = self.cache[@"Country"][serverKey]; 
Country *country = [self.context objectWithID:objectID] 

这将大大加快。

在解析JSON时创建新对象时,需要在获取permanent ID后将其服务器密钥和对象ID对添加到缓存中。删除对象时,从缓存中删除该对。