5

Core Dataストレージから2つのテーブル/モデルに対して「結合」タイプの操作を実行する必要があり、このようなものを機能させるための良い例を見つけるのに苦労しています。

私がしなければならないことはかなり簡単です。2つのモデル/テーブルがあります。locationsとlocation_categoriesです。ここで、locationsにはロケーション/施設の詳細が(一意のIDとともに)含まれ、location_categoriesテーブルにはcategory_idと関連付けられたlocation_idが含まれます。category_idを指定して、2つのテーブル/モデルを結合するすべての場所を選択する必要があります。ストレートSQLの場合、次のようになります(実際のSQLite DBに対して実行すると、このクエリは機能します)。

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

ご覧のとおり、これは非常に簡単です。2つのフェッチと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;
}

これが単一の述語/フェッチで可能かどうかについて何か考えはありますか?またはdunno..おそらくobjective-cコードを介してこれら2つのNSArrayを結合するより効率的な方法がありますか?

あなたがこれで提供できるどんな方向性にも前もって感謝します!

4

3 に答える 3

3

最良の方法は、関係を使用することです。

このようにフェッチすると、同様のものLocationにアクセスすることもできますLocationCategorymyLocation.locationCategory

次のように関係を設定する必要があります。

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

それは多対の関係です。逆も忘れないでください。

それが設定されたら、エンティティインスタンスを作成する場所で関係を接続する必要があります。好き:

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

また、同じMOCを使用してオブジェクトをフェッチしていることを確認してください。指定されたmocでのオブジェクトの作成とフェッチを簡単に管理するには、MagicalRecordを強くお勧めします。

于 2012-12-06T22:45:16.190 に答える
2

コア データと関係についてお読みください。関連エンティティの他のオブジェクトのセットを自動的に作成します。したがって、上記のケースで、Locations を 1 つのエンティティとして、Location_Categories を別のカテゴリとして持つ場合、必要なのは Locations テーブルに Location Categories エンティティを指す関係を作成することだけです。

これは、Core Data Modeling 画面で行うことができます。

これを行うと、Location 管理オブジェクト クラスには Location カテゴリの NSSet が含まれます。同様に、Location Categories Entity には Location のオブジェクトが含まれます。

したがって、上記の方法と同じように、ロケーション カテゴリの 1 つのクエリを実行するだけで済みます。ただし、追加のクエリを実行する代わりに、実行する必要があります

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からlocationsへの関連付けがあり、locationからlocation_categoriesへの逆の関係があります。したがって、「Location」というエンティティがある場合、そのエンティティにはlocationCategoryという名前の関係があり、LocationCategoryエンティティにはLocationという名前の関係があります。

このような双方向の関係を定義したら、次のようなものを使用してフェッチ要求を設定します。

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

これにより、特定のカテゴリIDを持つロケーションカテゴリに関連付けられているすべてのロケーションオブジェクトが返されます。

于 2012-12-06T22:46:41.640 に答える