将大型数据集导入核心数据,在Swift

时间:2016-08-10 21:21:44

标签: ios objective-c swift core-data relationship

我有一个CoreData数据库,里面有大约500,000枚邮票和86.000系列。我必须从使用JSON的web api下载它们。将邮票和系列添加到核心数据中没有问题。但在两者之间建立关系时我遇到了麻烦。

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

我需要有效和快速地建立两者之间的关系。当我做一些研究时,我偶然发现了这个网站https://www.objc.io/issues/4-core-data/importing-large-data-sets-into-core-data/我最感兴趣的那篇:

  

在建立关系时经常会出现类似的问题   新导入的对象。使用获取请求获取每个相关的   对象独立是非常低效的。有两种可能   解决这个问题的方法:要么我们分批解决关系   我们如何首先导入对象,或者我们缓存   已导入对象的objectID。解决关系   批量允许我们大大减少获取请求的数量   一次获取许多相关对象所需。别担心   潜在的长谓词如:

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

在IN(...)子句中解析具有许多标识符的谓词是   总是比为每个对象转到磁盘更有效   独立。但是,还有一种方法可以避免获取请求   完全(至少如果你只需要建立关系   在新导入的对象之间)。如果缓存所有的objectID   导入的对象(在大多数情况下真的不是很多数据),   您可以稍后使用它们来检索相关对象的故障   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;
     

请注意,此示例假定identifier属性是唯一的   跨所有实体类型,否则我们将不得不考虑   我们缓存的方式中不同类型的重复标识符   对象ID。

但我不知道他们的意思是什么,有人可以对此作出更多解释。最好是在Swift中,因为这是我理解的最好的语言,也是我正在创建我的应用程序的语言。 当然其他建议也没关系。 注意,离开CoreData不再是一个选项了。

1 个答案:

答案 0 :(得分:3)

在两个对象之间建立关系的任务涉及掌握这两个对象。考虑到它们已经在Core Data中创建,您可以使用类似

的谓词执行获取请求
@"countryID == %@", countryObjectData[@"id"]

你会得到它们。但是如果你需要建立五十万个关系,你将不得不执行一百万个获取请求。这很慢。

NSManagedObject检索NSManagedObjectID明显比按属性值搜索更快。在开始解析之前,您可以按server key -> objectID对的形式按实体构建所有Core Data对象的缓存。

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后将其服务器密钥和objectID对添加到缓存中。删除对象时从缓存中删除该对。