如何有效地为大型核心数据集建立关系?

时间:2014-05-31 23:51:42

标签: ios json core-data

我有两个实体饮料和啤酒厂。我在Json中有数据,我正在为每个建立核心数据表,并建立了一个关系(饮料到啤酒厂一对一)。然而,尝试在构建Drink对象时设置它显然会大大减慢这个过程,因为每次创建一个新饮料时我都要查询核心数据(有几千个饮料和大约1000个啤酒厂)。目前,啤酒厂有一个与饮料属性相匹配的唯一ID。在不减慢加载时间的情况下,最好的方法是什么?我正在考虑只使用一个实体并将啤酒厂放在同一个表中,即使这是糟糕的数据库实践。

以下是从json构建饮料表的代码,其中添加了啤酒厂中添加的代码。

[jsonCategories enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    Drink *drink = [NSEntityDescription insertNewObjectForEntityForName:@"Drink" inManagedObjectContext:importContext];
    //drinkType.id = [obj objectForKey:@"id"];
    drink.name = [obj objectForKey:@"name"];
    drink.alcoholByVolume = [obj objectForKey:@"abv"];
    drink.drinkType = beerDrinkType;
    drink.breweryId = [obj objectForKey:@"brewery_id"];


//        NSArray *fetchedObjects;
//        NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
//        NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Breweries" inManagedObjectContext:importContext];
//        [fetch setEntity:entityDescription];
//        [fetch setPredicate:[NSPredicate predicateWithFormat:@"id =%@", drink.breweryId]];
//        NSError *errorBrewery;
//        [fetch setFetchLimit:1];
//        fetchedObjects = [importContext executeFetchRequest:fetch error:&errorBrewery];
//        if (fetchedObjects && [fetchedObjects count] > 0){
//        Breweries *fetchedBrewery = [fetchedObjects objectAtIndex:0];
//        drink.breweries = fetchedBrewery;
//        }

}];

1 个答案:

答案 0 :(得分:0)

您正在使用jsonCategories元素的每次迭代重新获取brewery列表。这会增加巨大的开销并导致缓慢,并且是不必要的,因为我认为列表不会改变。

更好的设计是获取一次,然后根据需要对其进行过滤。我在下面省略了一些代码,只写了重要的部分,你应该能够自己填写。

NSFetchRequest *fetch = …;
// Note that predicate is not set here
fetchedBreweries = [importContext executeFetchRequest…];
[jsonCategories enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    …
    NSArray *matchingBreweries = [fetchedBreweries filteredArrayUsingPredicate:…predicate];
    drink.breweries = matchingBreweries.firstObject;
}];

也许这也会很慢,因为如果你拿到所有的啤酒厂,它可能会消耗太多的CPU和内存(虽然我先试着看看这是不是真的有问题)。

进一步优化可能是您首先遍历jsonCategories并创建一组在结果中找到的啤酒厂ID。然后,您只获取这些啤酒厂,然后再次重复饮料结果,将啤酒厂添加到饮料中。这就像是

NSMutableSet *breweryIds = [NSMutableSet set];
[jsonCategories enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    …
    [breweryIds addObject:[obj objectForKey:@"brewery_id"]];
}];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
[fetch setPredicate:[NSPredicate predicateWithFormat:@"id in %@", breweryIds]];
NSArray *breweries = [importContext executeFetchRequest…]
for (Drink *drink in drinks) {
    NSArray *matchingBreweries = [fetchedBreweries filteredArrayUsingPredicate:…predicate];
    drink.breweries = matchingBreweries.firstObject;
}

嗯。我现在需要一杯啤酒。