3

我无法理解如何最好地使用 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对象并构建一组艺术家,然后在最后找到集合的大小。此示例数据和代码的结果集将是计数 = 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

记录不佳的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的文档指出“子查询表达式的字符串格式是:”

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 回答