链式expression式在Core Data中执行计算

首先:新年快乐:-)

我正在尝试做什么

我试图在核心数据中划分两个属性,然后计算这些分区的平均值。 属性由关键path(例如eurusdaud )指定。

示例:我有以下数据集:

 date eur usd aud ------------------------------ 2010-01-01 0.5 1.0 1.5 2010-01-02 0.6 1.1 1.6 2010-01-03 0.4 1.0 1.3 

将两个属性分开,例如eur / usd与下面的结果…

 divide eur / usd: ------------------ 2010-01-01 0.5 2010-01-02 0.54 2010-01-03 0.4 

…然后计算这些数字的平均值(0.5 + 0.54 + 0.4)/3 = 0.48

我的代码

由于我想这些计算由Core Data直接执行,所以我创build了以下expression式和获取请求:

 NSExpression *fromCurrencyPathExpression = [NSExpression expressionForKeyPath:fromCurrency.lowercaseString]; NSExpression *toCurrencyPathExpression = [NSExpression expressionForKeyPath:toCurrency.lowercaseString]; NSExpression *divisionExpression = [NSExpression expressionForFunction:@"divide:by:" arguments:@[fromCurrencyPathExpression, toCurrencyPathExpression]]; NSExpression *averageExpression = [NSExpression expressionForFunction:@"average:" arguments:@[divisionExpression]]; NSString *expressionName = @"averageRate"; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = expressionName; expressionDescription.expression = averageExpression; expressionDescription.expressionResultType= NSDoubleAttributeType; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([self class])]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date >= %@ AND date <= %@",startDate,fiscalPeriod.endDate]; request.predicate = predicate; request.propertiesToFetch = @[expressionDescription]; request.resultType = NSDictionaryResultType; NSError *error; NSArray *results = [context executeFetchRequest:request error:&error]; 

问题

但是,运行应用程序时,它会崩溃,并显示错误消息:

 Unsupported argument to sum : ( "eur / usd" 

我的代码有什么问题? 我如何链接两个计算,并让他们直接在Core Data中执行?

谢谢!

似乎像@average这样的“集合”函数expression式只能用于关键path,而不能与其他通用expression式结合使用,当用作propertiesToFetch 。 我没有这方面的参考,但也是别人也注意到的一个问题:

  • 使用另一个expression式作为sum:expression的参数从NSManagedObject获取聚合数据
  • 用CoreData执行乘法(聚合):如何?

所以你可以分两步进行:首先执行一个获取请求,返回一个包含所有分区结果的数组:

 NSExpression *fromCurrencyPathExpression = [NSExpression expressionForKeyPath:@"eur"]; NSExpression *toCurrencyPathExpression = [NSExpression expressionForKeyPath:@"usd"]; NSExpression *divisionExpression = [NSExpression expressionForFunction:@"divide:by:" arguments:@[fromCurrencyPathExpression, toCurrencyPathExpression]]; NSString *expressionName = @"ratio"; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = expressionName; expressionDescription.expression = divisionExpression; expressionDescription.expressionResultType= NSDoubleAttributeType; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"]; request.propertiesToFetch = @[expressionDescription]; request.resultType = NSDictionaryResultType; NSError *error; NSArray *ratios = [context executeFetchRequest:request error:&error]; 

结果是一个字典数组:

 (lldb) po ratios (NSArray *) $0 = 0x00000001001170f0 <_PFArray 0x1001170f0>( { ratio = "0.5454545454545454"; }, { ratio = "0.4"; }, { ratio = "0.5"; } ) 

另外,使用“-com.apple.CoreData.SQLDebug 1”选项,可以看到分区已经在SQLite级别上执行了:

 sql: SELECT t0.ZEUR / t0.ZUSD FROM ZENTITY t0 

然后,您可以使用键值编码来计算内存中所有比例的平均值:

 NSNumber *average = [ratios valueForKeyPath:@"@avg.ratio"]; 

结果是

 (lldb) po average (NSNumber *) $0 = 0x000000010012fd60 0.4818181818181818