我无法理解如何最好地使用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;
答案 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