2016-08-10 38 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對添加到緩存中。刪除對象時,從緩存中刪除該對。