【发布时间】:2014-11-19 06:56:43
【问题描述】:
我有一个非常大的 CoreData 表,其中包含这样的元素(简化):
@interface Medicament : NSManagedObject
@property (nonatomic, retain) NSString * identifier;
@property (nonatomic, retain) NSString * name;
@end
在某些时候,我想找到具有相同属性的元素(并丢弃其余的),类似于 SQLite 语句:
SELECT name, COUNT(*) AS count FROM Medicament GROUP BY name WHERE count > 1
为此,我有这个 CoreData 查询:
NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:@"Medicament"];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Medicament"
inManagedObjectContext:self.managedObjectContext];
NSAttributeDescription* identifierDesc = [entity.attributesByName objectForKey:@"identifier"];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"identifier"];
NSExpression *countExpression = [NSExpression expressionForFunction: @"count:"
arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: @"count"];
[expressionDescription setExpression: countExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];
[fetch setPropertiesToFetch:[NSArray arrayWithObjects:identifierDesc, expressionDescription, nil]];
[fetch setPropertiesToGroupBy:[NSArray arrayWithObject:identifierDesc]];
[fetch setResultType:NSDictionaryResultType];
NSError* error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetch
error:&error];
这似乎正确地返回了具有以下格式的字典列表:
{
count = 1;
identifier = 65023;
},
{
count = 2;
identifier = 65025;
},
{
count = 1;
identifier = 65027;
}
问题是我想丢弃所有count 等于1 的结果。
我尝试在 fetch 中添加一个谓词,希望 CoreData 足够聪明,像这样:
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"count > 1"];
fetch.predicate = predicate;
但它会因错误keypath count not found in entity <NSSQLEntity Medicament id=11> 而崩溃。
这甚至可以使用 CoreData,还是我必须在从数据库中获取结果后过滤结果?
这是我目前过滤已从数据库加载的对象的方法:
NSPredicate* filterPredicate = [NSPredicate predicateWithFormat:@"count > 1"];
NSArray* filteredResults = [results filteredArrayUsingPredicate:filterPredicate];
但我希望这个简单的计算可以由 CoreData 或 SQLite 执行,这可能会更有效。
【问题讨论】:
-
您在这里所做的是将谓词设置为实体设置为 Medicament 的 fetch 请求,因此 Medicament 没有名为 count 的属性!您可以创建一个具有标识符和计数属性的模型,用您从 coredata 获得的结果填充它,然后使用此谓词过滤该模型的数组。所以是的,我认为您必须先从 coredata 获取结果,然后过滤它们。
-
@NofelMahmood 是的,这是一次无望的尝试。我猜数据库引擎执行该操作的速度比我通过代码执行的快得多。目前数据库有 30k 行,大约 28k 将被丢弃。所以我会从数据库中加载大量我不需要的数据。
-
你用过NSFetchRequest的“havingPredicate”特性吗?
-
您可以通过设置获取请求批量大小来减少内存开销。默认情况下它设置为 0,这反过来将结果的所有对象都带入内存。如果将其设置为 20,它将仅在内存中带入 20 个对象,当您尝试访问它们时,下一个 20 将带入内存,依此类推:)
-
@pbasdf 是的,使用
havingPredicate没有任何区别。同样的错误
标签: ios objective-c sqlite core-data