0

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]];
4

1 に答える 1

0

2 つのエラーが表示されます。の初期化は示されていませんtoDate。NSExpressions の配列を渡していることにも気付きsetPropertiesToFetch:ましたが、ドキュメントでは NSPropertyDescriptions の配列が必要です。フェッチ要求を実行すると、その不一致により結果が null になり、NSError が入力されることが予想されます。

からどのような結果が見えexecuteFetchRequest:error:ますか? NSError の結果を確認してください。イディオムは次のようなものです。

    NSError *error;
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    if (!results) {
        NSLog(@"%@ fetch error for request %@: %@ %@", fetchRequest,
              error.localizedDescription, error.localizedFailureReason);
    }

私は別のアプローチを取るでしょう。1 つのフェッチ リクエストには 1 の制限があり、timestamp降順で並べ替えられ、最新のtimestamp. 時間制限のために、必要に応じて述語を追加します。次に、2 番目のフェッチ リクエストを使用して、タイムスタンプの平均を計算します。これらの呼び出しを独自のメソッドにカプセル化することもできます。

-(NSDate *)latestTimestamp:(NSManagedObjectContext *)moc;

-(NSNumber *)averageValueSinceTime:(NSDate *)intervalStart
                           context:(NSManagedObjectContext *)moc;
于 2012-12-29T00:08:30.430 に答える