代码之家  ›  专栏  ›  技术社区  ›  Kevin Hakanson

使用来自核心数据的NSFetchRequest来获取聚合关系计数?

  •  3
  • Kevin Hakanson  · 技术社区  · 13 年前

    我很难理解如何最好地使用核心数据来解决这个问题,包括描述这个问题的正确术语。下面是这个问题的示例(但不是我的实际对象)。假设你有一个音乐播放系统,艺术家有歌曲,每次在系统中播放歌曲时,都会记录时间戳。

    问题: 我如何才能找到播放歌曲的艺术家的数量?

    这是样品 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;
    
    2 回复  |  直到 13 年前
        1
  •  4
  •   Kevin Hakanson    13 年前

    记录不足 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];
    

    我还没有测试那个子查询字符串,但这应该会让你开始。如果你在谷歌上搜索的话,那里有一些不错的资源,但苹果文档中的资源并不多。的文档 NSExpression 声明“子查询表达式的字符串格式为:”

    SUBQUERY(集合表达式、变量表达式、谓词);

        2
  •  1
  •   Community Mohan Dere    8 年前

    您可以尝试以下操作: 按播放次数超过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