使用Core Data中的NSFetchRequest获取聚合关系计数?

时间:2012-08-26 19:41:29

标签: ios core-data relationship nsmanagedobject nsfetchrequest

我无法理解如何最好地使用Core Data来解决此问题,包括描述问题的正确术语。下面是问题的说明性示例(但不是我的实际对象)。假设您有一个音乐播放系统,艺术家有歌曲,每次在系统中播放一首歌曲时,都会记录时间戳。

问题:如何找到播放歌曲的艺术家人数?

以下是示例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个对象并构建一组艺术家,然后在最后找到该组的大小。此示例数据和代码的结果集将是[A1,A2],其中count = 2.但是,我希望某些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;

2 个答案:

答案 0 :(得分:4)

记录欠佳的SUBQUERY可能是一个很好的解决方案,您可以嵌套它们,以便检查关联关联。

所以:

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];

我还没有测试过该子查询字符串,但这应该可以让你开始。如果你谷歌为他们提供了一些很好的资源,但在Apple文档中并不多。 NSExpression的文档说明子查询表达式的&#34;字符串格式为:&#34;

  

SUBQUERY(collection_expression,variable_expression,predicate);

答案 1 :(得分: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];

查看有关唯一数据结果获取的详情: Retrieving a unique result set with Core Data