优化此核心数据请求

时间:2013-04-09 13:05:08

标签: iphone ios objective-c core-data

我在Core Data中有一个名为MusicInterest的实体。我必须一次添加5000个左右,我当前的过程是查询MusicInterest是否已经存在,如果没有创建一个新的。

这似乎需要5000次前往商店才能查看每个标题是否存在。当然,还有插入行程,但5000次查询正在减慢我的速度。

每个FacebookFriend都会有多个音乐兴趣,我使用一系列字符串标题枚举每个音乐兴趣,并调用以下代码。

有任何想法如何优化这个?

+ (MusicInterest*) musicInterestForFacebookFriend:(FacebookFriend*)facebookFriend WithTitle:(NSString*)musicTitle UsingManagedObjectContext:(NSManagedObjectContext*)moc
{
    // query to see if there
    NSArray *matches = [self queryForMusicTitle:musicTitle moc:moc];

    if (([matches count] >= 1)) {
        // NSLog(@"Music already in database");
        MusicInterest *existingMusic = [matches lastObject];
        [existingMusic addLikedByObject:facebookFriend];
        return [matches lastObject];
    } else {
        // create new Music Interest
        MusicInterest *newMusic = [NSEntityDescription insertNewObjectForEntityForName:@"MusicInterest" inManagedObjectContext:moc];
        newMusic.title = musicTitle;
        [newMusic addLikedByObject:facebookFriend];
        return newMusic;
    }
}

+ (NSArray *)queryForMusicTitle:(NSString *)MusicTitle moc:(NSManagedObjectContext *)moc
{
    // query to see if there
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MusicInterest"];
    request.predicate = [NSPredicate predicateWithFormat:@"title == %@", [NSString stringWithFormat:@"%@", MusicTitle]];

    NSError *error = nil;
    NSArray *matches = [moc executeFetchRequest:request error:&error];
    if (error) {
        NSLog(@"Error querying title in Music interest. Error = %@", error);
    }
    return matches;
}

更新:

我使用了Core Data编程指南中建议的设计,它将我的时间从12秒减少到4秒(在其他方面仍然需要一些优化:)

指南只包含示例代码的一半 - 我想我会分享我的完整实现:​​

musicArray = [[music componentsSeparatedByString:@", "] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
                if (obj1 > obj2)
                    return NSOrderedDescending;
                else if (obj1 < obj2)
                    return NSOrderedAscending;
                return NSOrderedSame;
            }];

            if (musicArray) {

                NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"MusicInterest"];
                [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"title IN %@", musicArray]];
                [fetchRequest setSortDescriptors:
                 @[[[NSSortDescriptor alloc] initWithKey: @"title" ascending:YES]]];

                NSError *fetchError = nil;
                NSArray *musicInterestMatchingTitles = [backgroundContext executeFetchRequest:fetchRequest error:&fetchError];

                if ([musicArray count] > 0) {
                    // walk musicArray and musicInterestsMatchingTitles in parallel
                    for (int i = 0; i < [musicArray count]; i++) {
                        NSString *title = musicArray[i];
                        if (i < [musicInterestMatchingTitles count]) {
                            MusicInterest *comparingMusicInterest = musicInterestMatchingTitles[i];
                            // compare each title
                            if (![title isEqualToString:comparingMusicInterest.title]) {
                                // if it doesn't exist as a ManagedObject (a MusicInterest), create one
                                MusicInterest *musicInterest = [MusicInterest createNewMusicInterestUsingManagedObjectContext:backgroundContext];
                                musicInterest.title = title;
                                [musicInterest addLikedByObject:friend];
                            } else {
                                // otherwise, just establish the relationship
                                [comparingMusicInterest addLikedByObject:friend];
                            }
                        } else {
                            // if there are no existing matching managedObjects, create one
                            MusicInterest *musicInterest = [MusicInterest createNewMusicInterestUsingManagedObjectContext:backgroundContext];
                            musicInterest.title = title;
                            [musicInterest addLikedByObject:friend];
                        }
                    }
                }
            }

        }];
        [self saveBackgroundContext:backgroundContext];

1 个答案:

答案 0 :(得分:3)

“核心数据编程指南”中的

Implementing Find-or-Create Efficiently描述了一种在这里可能有用的模式。基本思路是:

  • 按照存储在其中的某个唯一ID对要插入/更新的项目列表进行排序 数据库。
  • 执行单次提取请求,从数据库中提取具有列表中id的所有对象,并按相同的ID排序。
  • 现在并行遍历您的列表和获取的项目数组,以查找必须插入的项目以及哪些项目已存在且可以更新。