5

私の人生では、これを機能させることができないようです。

エンティティがステータスフィールドと注文フィールドを持つ管理対象オブジェクトであると想定します。

同じ注文が複数あるすべてのorderedEntriesを取得するにはどうすればよいですか?

メイン述語に@countを使用してサブクエリを実行するように指示する回答はありません。その解決策を知っているので、この投稿のポイントは、コアデータで持つ述語を使用する方法を理解することです。とにかくサブクエリ。(私がhave句を使用できない理由を説明しない限り)

次のコードは、注文番号ごとの注文数を含む辞書の配列を返します。私が欲しいのは、1より大きいカウントを持つ注文のオブジェクトを表すディクショナリのみを返すように要求を制限するために、have句を追加できるようにすることです。

これまでのコードと、述語を持つことを試みた私の試みは次のとおりです。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OrderedEntry"
                                          inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setResultType:NSDictionaryResultType];

NSPredicate *predicate = [NSPredicate predicateWithFormat:
                 @"(status == %@)",[NSNumber numberWithInt:EntryStatusAlive]];


[fetchRequest setPredicate:predicate];


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"order"]; // Does not really matter
NSExpression *maxExpression = [NSExpression expressionForFunction: @"count:"
                                                        arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: @"orderCount"];
[expressionDescription setExpression: maxExpression]; 
[expressionDescription setExpressionResultType: NSInteger32AttributeType];

[fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects:expressionDescription,@"order",nil]];


[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObjects:@"order",nil]];
//[fetchRequest setHavingPredicate:[NSPredicate predicateWithFormat:@"@count > 1"]];
//[fetchRequest setHavingPredicate:[NSComparisonPredicate predicateWithLeftExpression:maxExpression rightExpression:[NSExpression expressionForConstantValue:[NSNumber numberWithInteger:1]] modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:NSCaseInsensitivePredicateOption]];

NSError *error;

NSArray * array = [context executeFetchRequest:fetchRequest error:&error];
4

3 に答える 3

1

私は興味のある人のためにこれを使うことになりました

-(BOOL)ordersAreSaneOnDay:(NSNumber*)dayNumber forUser:(User*)user inContext:(NSManagedObjectContext*)context {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"BasicEntry"
                                          inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setResultType:NSDictionaryResultType];

NSPredicate *predicate = [NSPredicate predicateWithFormat:
                 @"(status == %@) && ((type != %@) && (type != %@) && (dayNumber == %@))  && ((user == NIL) || (user == %@))",[NSNumber numberWithInt:EntryStatusAlive],[NSNumber numberWithInt:EntryTypeTask],[NSNumber numberWithInt:EntryTypeCompletedTask],dayNumber,user];


[fetchRequest setPredicate:predicate];


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"order"]; // Does not really matter
NSExpression *maxExpression = [NSExpression expressionForFunction: @"count:"
                                                        arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: @"orderCount"];
[expressionDescription setExpression: maxExpression]; 
[expressionDescription setExpressionResultType: NSInteger32AttributeType];

[fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects:expressionDescription,@"order",nil]];
[expressionDescription release];

[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObjects:@"order",nil]];
//[fetchRequest setHavingPredicate:[NSPredicate predicateWithFormat:@"self.order.@count > 1"]];
//[fetchRequest setHavingPredicate:[NSComparisonPredicate predicateWithLeftExpression:maxExpression rightExpression:[NSExpression expressionForConstantValue:[NSNumber numberWithInteger:1]] modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:NSCaseInsensitivePredicateOption]];

NSError *error;

NSArray * array = [context executeFetchRequest:fetchRequest error:&error];
array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"orderCount > 1"]];
//NSLog(@"it worked %@",array);
[fetchRequest release];

if ([array count]) return FALSE;
return TRUE;

}

于 2013-01-22T15:08:19.690 に答える
0

まず、あなたがしていることに類似したことを試みるたびに、対多関係を に渡すことができないというエラーが表示されますsetPropertiesToFetch:NSFetchRequest のドキュメントはこれを裏付けています

問題#2は、対多関係でもグループ化できないように見えることです(これはドキュメントでは明確にされていませんが、同じエラーが発生し、それも理にかなっています).

取得するプロパティから「注文」を削除します。属性でグループ化します。主な述語を変更して、グループ化する属性のみを含める (または単に削除する) ようにします。having述語に「order」を指定します。

[fetchRequest setPropertiesToGroupBy: @[ @"???" ]];
[fetchRequest setHavingPredicate: [NSPredicate predicateWithFormat: @"self.order.@count > 1"]];

これで、リクエストが機能することがわかりますが、結果はおそらく期待したものではありませんでした:

 - NSArray
     - NSDictionary { status = @"alive", orderCount = "4" }
     - NSDictionary { status = @"alive", orderCount = "9" }
     - NSDictionary { status = @"alive", orderCount = "2" }
     - etc...

NSDictionaryResultType実際には、これらのオブジェクトを識別するための情報は何も提供しません。値を提供するだけです。

次のステップは、それらのOrderedEntryオブジェクトの ID を取得することです。トリックは、NSManagedObjectID を各ディクショナリのキーとして返す式を含めることです。

これにより実際にパフォーマンスが向上するかどうかはわかりません(メインの述語にANDするだけではありません)。私の経験では、フェッチのパフォーマンスを向上させるためにできる最善の方法の 1 つは、シングルトン NSPredicate を作成し、置換変数を使用して各フェッチをセットアップすることです。述語の解析はコストがかかる可能性があります。

ディクショナリの結果の型は面倒な場合があります。通常は、適切な述語を作成するだけで十分です。私はそれらを式にのみ使用する傾向があります(つまり、値を返すグラフで統計タイプの計算を実行します)。フェッチしてグループ化するためのプロパティに関するすべての制限と、述語の制限を見ると、これは Apple が意図していることのようです。グループ化して述語を使用することで、やりたいことを実行できるかどうかさえわかりません。たとえば、何によってグループ化しますか? ステータス別 (述語に含めるためにグループ化する必要があります) の場合、すべての OrderEntries が折りたたまれず、個別の objectID と orderCounts を取得できませんか? これについては、グループ化して述語を使用するのではなく、主要な述語に固執するのが最善です。

于 2013-01-21T18:10:55.120 に答える