1

昨日、もっと単純な例から始めるべきだった質問をしました。質問を基本に絞り込んだので、既存の SO の質問と回答を使用して問題を解決できました。

これを十分に明確に説明する投稿がないと思うので、ここで質問を要約しています(そして私自身の解決策を提供しています)。Core Data を初めて使用し、SQL の概念から抜け出すのに苦労しているので、私のソリューションがどれほど適切であるか、また問題をモデル化するためのより良い方法があるかどうかについてのフィードバックを歓迎します。

質問

次のオブジェクト モデルには、3 つのエンティティ A、B、および C があり、それぞれが対多リレーションシップによってリンクされています。

モデル

特定の属性を持つ孫Cエンティティを持つ親Aエンティティを特定するにはどうすればよいでしょうか? 例として、これらのサンプル エンティティとその関係を使用します。

例

どのエンティティAが Tag:Yes を持つ子エンティティCを持っているかを調べるにはどうすればよいですか?

解決

SUBQUERYのキーワードを使用してこれを達成できましたNSPredicate。これが私のために働いたコードスニペットです(管理対象オブジェクトのコンテキストなどを設定していると仮定します):

NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"EntityA" inManagedObjectContext:context];   
[fetchRequest setEntity:entity];
NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:@"(0 != SUBQUERY(child, $a, (0 != SUBQUERY($a.child, $child, $child.tag == %@).@count)).@count)", @"YES"]; 
[fetchRequest setPredicate:predicateTemplate];
NSArray *test = [context executeFetchRequest:fetchRequest error:&error];

すべての重要な NSPredicate 文字列をいくつかの行に分割します。

(0 != SUBQUERY(child, 
               $a, 
               (0 != SUBQUERY($a.child,
                              $child, 
                              $child.tag == %@).@count)
               ).@count
)

重要な部分は、EntityA作業する を選択してから、ネストされたサブクエリでchildエンティティの関係を処理することです。これをいくつかの深さで繰り返すことができると思います。まとめるのに最も直感的なものではありません...しかし、うまくいきます。コメント歓迎。

4

2 に答える 2

2

コア データ ガイドラインに従い、相互関係を設定している場合は、下から検索してみることができます。

必要な述語を渡すエンティティ C オブジェクトを取得し、親を上ってエンティティ A オブジェクトを取得します。ネストされたサブクエリは必要ありません。

編集して追加

parentリレーションシップから C の親 (B のオブジェクト) を取得できます。そこから、parent関係から親 (A のオブジェクト) を取得できます。

コア データ モデル ダイアグラムにあります。

于 2012-10-05T18:27:51.297 に答える
2

私はこれまでサブクエリを使用したことがありませんでした。これは非常にクールで、その例を見るのは良いことです。実際に質問への回答としてソリューションを追加する必要があります!

これはツリーのような階層であり、対1の関係を使用してツリーを上に移動する方が簡単なので、私はおそらくAbizernが提案したようにしたでしょう。

コードでは、これは次のようになります。

NSManagedObjectContext *moc = APPDELEGATE.managedObjectContext;
NSFetchRequest *request = [NSFetchRequest new];
[request setEntity:[NSEntityDescription entityForName:@"EntityC" inManagedObjectContext:moc]];
[request setPredicate:[NSPredicate predicateWithFormat:@"tag = YES"]];
NSError *fetchError = nil;
NSArray *children = [moc executeFetchRequest:request error:&fetchError];

childrenEntityC述語に一致するオブジェクトの配列です。次のステップは、これらの「祖父母」である一意のEntityAオブジェクトのセットを取得することです。ここでキー値コーディングを利用できます。

NSArray *grandParents = [children valueForKeyPath:@"parent.@distinctUnionOfObjects.parent"];

この場合、効率のために、おそらくparent.parent最初のフェッチ リクエスト中にキーパスをプリフェッチする必要があります。

[request setRelationshipKeyPathsForPrefetching:@[@"parent.parent"]];

お役に立てれば!

于 2012-10-06T03:47:59.520 に答える