iOS : 如何获取核心数据中最大计数的对象?

iOS : How to fetch objects with maximum count in core data?

我的核心数据模型中有两个 类,并且是一对多关系。

让我们以Class专辑<--->>Class歌曲来解释。现在我想从 Album 中获取(前)五张专辑,其中最大的 no.of Songs.

Class Album
{
    albumID (Integer)
    name    (String)
    songs   (class B)
}

Class Songs
{
    name   (String)
    length (Integer)
}

@class Songs;
@interface Album : NSManagedObject

@property (nonatomic, retain) NSNumber * albumID;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *songs;

@end

@interface Album (CoreDataGeneratedAccessors)
- (void)addSongsObject:(Songs *)value;
- (void)removeSongsObject:(Songs *)value;
- (void)addSongs:(NSSet *)values;
- (void)removeSongs:(NSSet *)values;
@end

@class Album;

@interface Songs : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * length;
@property (nonatomic, retain) Album *owner;

@end

这是我正在尝试的,

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];
fetchRequest.fetchOffset = 0;
fetchRequest.fetchLimit = 5;
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"albumID" ascending:YES]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SELF @max.@count.songs"];
NSError *error = nil;
NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];

如果我不传递谓词,它工作正常。但问题在于谓词。它使应用程序崩溃并显示以下消息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "SELF @max.@count.songs"'

Update:我正在对 NSExpression 进行同样的尝试,但无法同时执行 max:count: 函数?下面是我试过的,

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];

fetchRequest.fetchOffset = 0;
fetchRequest.fetchLimit = 5;

NSError *error = nil;

NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"songs"];
NSExpression *countExpression = [NSExpression expressionForFunction:@"count:" arguments:[NSArray arrayWithObject:keyPathExpression]];
//NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *maxCountExpressionDescription = [[NSExpressionDescription alloc] init];
[maxCountExpressionDescription setName:@"squishes"];
[maxCountExpressionDescription setExpression:countExpression];

[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:maxCountExpressionDescription]];
[fetchRequest setResultType:NSDictionaryResultType];

NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];

我想,我需要这样查询,

SELECT album.name, max(count(album.songs)) FROM Album;

如何在 NSFetchRequest 中创建这样的查询,是否可以使用 NSExpressionNSPredicate

尝试删除:

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SELF @max.@count.songs"];

并将您的排序描述符替换为:

fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"songs.@count" ascending:NO]];

我用不同的方法解决了这个问题,我在相册 class 中添加了 songsCount 属性。每次我 add/remove 专辑中的歌曲时,我都会 incrementing/decrement 它。然后我获取所有按 songsCount 降序排序的专辑。

一旦我可以获取所有相册,我将运行一个for循环并取出前五个对象。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"songsCount" ascending:NO]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"songsCount > 0"];
NSError *error = nil;
NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];
NSMutableArray *top5Albums = [NSMutableArray array];
NSInteger totalCounts = [albums count];
NSInteger maxIndex = (totalCounts >= 5) ? 5 : totalCounts;
for(NSInteger index = 0; index < maxIndex; index++) {
    [top5Albums addObject:[albums objectAtIndex:index]];
}