【问题标题】:Filter results in CoreData by entity description按实体描述过滤 CoreData 中的结果
【发布时间】: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


【解决方案1】:

您可以这样做的唯一方法是首先获取数据,然后从那里按计数过滤它。

如果您愿意,您可以向名为 count 的实体添加一个属性,然后您可以使用该谓词过滤您想要的实体(在这种情况下 count > 1),但您需要在 Mediment 实体中添加一个 count 属性这样做。

【讨论】:

  • 正如你在最后几行中看到的,这就是我正在做的事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
相关资源
最近更新 更多