3

問題を説明するための正しい用語を含め、この問題を解決するためにCoreDataを最適に使用する方法を理解するのに苦労しています。以下は、問題の実例となるサンプルです(ただし、実際のオブジェクトではありません)。アーティストが曲を持っている音楽再生システムがあり、システムで曲が再生されるたびにタイムスタンプが記録されるとします。

質問:曲を再生したアーティストの数を確認するにはどうすればよいですか?

こちらがサンプルですNSManagedObject

@interface MYArtist : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSSet *songs;
@end

@interface MYSong : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) MYArtist *artist;
@property (nonatomic, retain) NSSet *plays;
@end

@interface MYPlay : NSManagedObject
@property (nonatomic, retain) NSDate *playDate;
@property (nonatomic, retain) MYSong *song;
@end

以下は、アーティスト、曲、演劇のサンプルデータで、演劇の日付が含まれています。

A1 <-+-> S1_A1 <---> P1_S1_A1 (2012-08-31) 
     '-> S2_A1 <-+-> P1_S2_A1 (2012-08-31) 
                 '-> P2_S2_A1 (2012-09-01)
A2 <-+-> S1_A2
     '-> S2_A2 <---> P1_S2_A2 (2012-08-31) 
A3 <---> S1_A3 

以下のコードを使用して、すべてのオブジェクトをフェッチし、MYPlayアーティストのセットを作成して、最後にセットのサイズを見つけることができます。このサンプルデータとコードから得られるセットは、count = 2の[A1、A2]になります。ただし、オブジェクトを反復処理してメモリにフォールトするのではなく、NSPredicate構文またはの使用がより効率的であると期待します。countForFetchRequest

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MYPlay"];
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

NSMutableSet *set = [[NSMutableSet alloc] init];
for (id result in results) {
    MYPlay *play = (MYPlay *)result;
    [set addObject:play.song.artist];
}

NSUInteger count = set.count;
4

2 に答える 2

4

The poorly documented SUBQUERY might be a good solution, and you can nest them so you can check associations of associations.

So:

NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"MYArtist"]; 
request.predicate = [NSPredicate predicateWithFormat:@"(SUBQUERY(songs,$song,SUBQUERY($song.plays,$play,$play.playDate NOT NULL).@count > 0).@count >0)"]; // I'm assuming that songs with out a play have a nil playDate

NSUInteger count = [context countForFetchRequest:request error:&error];

I haven't tested that subquery string, but that should get you started. There's a few good resources out there if you google for them, but not much in the Apple docs. Documentation for NSExpression states the "string format for a subquery expression is:"

SUBQUERY(collection_expression, variable_expression, predicate);

于 2012-08-26T20:43:08.590 に答える
1

これを試すことができます: 再生回数が 0 を超える一意のアーティスト名で曲を取得します。

  NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MYSong"];
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"plays.@count > 0"];
  [request setPredicate:predicate];
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"MYSong" inManagedObjectContext:context];
  NSDictionary *entityProperties = [entity propertiesByName];
  [request setReturnsDistinctResults:YES];
  [request setPropertiesToFetch:[NSArray arrayWithObject:[entityProperties objectForKey:@"artist"]]];

  NSError *error = nil;
  NSArray *result = [managedObjectContext executeFetchRequest:request error:&error];

一意のデータ結果の取得について詳しくは 、Core Data を使用して一意の結果セットを取得するをご覧ください。

于 2012-08-27T04:35:04.903 に答える