Core Dataを使用して、値とタイムスタンプで構成される単純なエンティティを格納しています。最新の付加価値とすべての値の移動平均を返すフェッチリクエストを作成しようとしています。NSPredicateを使用して特定の期間内に結果をフィルタリングしようとするまで、これはすべて簡単に思えました。
NSExpressionのexpressionForFunction:withArguments:
メソッドを使用して平均を決定しています。起動フラグ-com.apple.CoreData.SQLDebug 1
を設定することで、最新の値のみが私の日付述語に準拠していることがはっきりとわかります。平均計算は代わりにサブクエリとして実行されますが、私の日付述語は考慮されていません。
SELECT (SELECT avg(t1.ZVALUE) FROM ZEVENT t1 WHERE t1.Z_ENT = ?), t0.ZVALUE FROM ZEVENT t0 WHERE ( t0.ZTIMESTAMP >= ? AND t0.Z_ENT = ?) ORDER BY t0.ZTIMESTAMP DESC
NSFetchRequestの述語を尊重しながら、平均値を決定する最も効率的な(そしてスケーラブルな)方法は何ですか?
参考までに、ここに私のコード全体を示します。
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Reading" inManagedObjectContext:moc];
[request setEntity:entity];
[request setSortDescriptors:@[sortDescriptor]];
[request setResultType:NSDictionaryResultType];
// Filter by date where necessary
NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"(timestamp >= %@)", toDate];
[request setPredicate:datePredicate];
NSExpression *valueExpression = [NSExpression expressionForKeyPath:valueKey];
NSExpressionDescription *valueDescription = [[NSExpressionDescription alloc] init];
[valueDescription setName:@"value"];
[valueDescription setExpression:valueExpression];
[valueDescription setExpressionResultType:NSDoubleAttributeType];
NSExpression *avgExpression = [NSExpression expressionForFunction:@"average:" arguments:[NSArray arrayWithObject:valueExpression]];
NSExpressionDescription *avgDescription = [[NSExpressionDescription alloc] init];
[avgDescription setName:@"averageReading"];
[avgDescription setExpression:avgExpression];
[avgDescription setExpressionResultType:NSDoubleAttributeType];
[request setPropertiesToFetch:@[avgDescription, valueDescription]];