5

我需要对我的核心数据存储中的两个表/模型进行“加入”类型的操作,而且我很难找到好的例子来让这样的事情发挥作用。

我需要做的事情相当简单。我有两个模型/表:位置和 location_categories,其中位置包含位置/机构的详细信息(以及唯一 ID),并且 location_categories 表包含具有关联 location_id 的 category_id。我需要选择给定 category_id 连接两个表/模型的所有位置。如果它是直接的 SQL,它看起来像这样(当我对实际的 SQLite DB 运行它时,这个查询确实有效):

// pretend we passed in a catID of 29:
SELECT * FROM zlocation where zlocid in (select zlocid from zloccategory where zcatid = 29)

如您所见,它非常简单。有没有办法做到这一点而不必进行两次提取和 for 循环?我目前执行此操作的objective-c 代码如下,它运行良好,但当然它非常缓慢且效率低下,因为两个表中都有大量数据。for 循环导致了巨大的减速,我的直觉告诉我,这项工作真的应该在 DB/Core-Data 方面完成:

- (NSMutableArray *) fetchLocsWithCatID:(NSString *)catID {
    NSMutableArray *retArr = [[NSMutableArray alloc] init];

    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:MODELNAME_LOCCATEGORIES inManagedObjectContext:context]];
    [fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"catID == %@", catID]];

    NSError *error;
    NSArray *locCats = [context executeFetchRequest:fetchRequest error:&error];
    NSArray *allLocsArr = [self fetchAllDataForTable:MODELNAME_LOCATION]; // this retrieves contents of entire table

    for (Location *currLoc in allLocsArr) {
        for (LocCategory *currLocCat in locCats) {
            if ([currLoc.locID isEqualToString:currLocCat.locID]) {
                if (![retArr containsObject:currLoc]) {
                    [retArr addObject:currLoc];
                }
            }
        }
    }

    return retArr;
}

关于这是否可以通过一个谓词/提取来实现的任何想法?或者不知道......也许有一种更有效的方法可以通过objective-c代码加入这两个NSArrays?

提前感谢您对此提供的任何指导!

4

3 回答 3

3

最好的方法是使用关系。

这样,当您获取 a 时,Location您还可以访问LocationCategorylikemyLocation.locationCategory

您需要像这样设置您的关系:

(Entity)LocationCategory.(relationship)locations <->> (Entity)Location.(relationship)locationCategory

这是一对多的关系。也不要忘记倒数。

设置好之后,您只需在创建实体实例的地方连接关系即可。像:

 Location *myLocation = ...
 LocationCategory *myLocationCategory = ...
 myLocation.locationCategoy = myLocationCategory;

还要确保您使用相同的 MOC 来获取对象。我强烈推荐MagicalRecord来轻松管理在指定 moc 中创建对象和获取。

于 2012-12-06T22:45:16.190 回答
2

阅读核心数据和关系。它将自动创建相关实体的其他对象集。因此,在上述情况下,如果您将 Locations 作为一个实体,将 Location_Categories 作为另一个类别,您需要做的就是在 Locations 表中创建一个指向 Location Categories 实体的关系。

您可以在 Core Data Modeling 屏幕中执行此操作。

一旦你这样做了,位置管理对象类将有一个位置类别的 NSSet。同样,Location Categories Entity 中也会有一个 Location 对象。

因此,您需要做的只是一个位置类别的查询,就像您在上面所做的那样。但是,您不需要做额外的查询

for (LocationCategory *locationCategory in locationCats) {
    NSLog(@"Location name is %@",locationCategory.location.locationName);
    // You can ofcourse add it to an arrary or what ever
}

任何核心数据教程都应该能够在这方面为您提供帮助。

于 2012-12-06T22:40:43.470 回答
1

如果这些实体在 CoreData 中建模,您通常会有从 location_categories 到 location 的关联,从 location 到 location_categories 具有反向关系。因此,如果我有一个名为“Location”的实体,它将在其中有一个名为 locationCategory 的关系,而在 LocationCategory 实体中,它将有一个名为 Location 的关系。

定义了这种双向关系后,我将使用以下内容设置获取请求:

[fetchRequest setEntity:[NSEntityDescription entityForName:MODELNAME_LOCATIONS inManagedObjectContext:context]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"locationCategory.catID == %@", catID]];

这应该返回与具有给定类别 ID 的位置类别相关联的所有 Location 对象

于 2012-12-06T22:46:41.640 回答