0

Core Data を使用して次の問題を解決しようとしていますが、運がありません。

私のモデルには、Group と Element の 2 つのエンティティがあります。「name」属性と「group.elements」および「element.groups」の形式の対多関係の両方 (複数のグループに属する要素と複数の要素を持つグループ)

次の形式で「フィルター」を確立したい:

elements that belongs to "group_A" AND "group_B"

ユーザーに次のようなものを表示するには:

The elements that match the filter belong to this set of groups in that quantity

例として、次のようなものがあります。

Element_1 Group_A、Group_B、Group_C
Element_2 Group_B、Group_C
Element_3 Group_A、Group_B、Group_D
Element_4 Group_A、Group_B、Group_D
Element_5 Group_C、Group_D

答えは次のようになります: Element_1、Element_3、および Element_4 がフィルターに一致し、表示される情報は次のようになります。

Group_A には 3 つの要素があります
Group_B には 3 つの要素があります
Group_C には 1つの要素があります
Group_D には 2 つの要素が

あり、フィルタに一致します

これをCore Data NSExpression、NSPredicateなどに入れるにはどうすればよいですか?

ありがとう。



アップデート

これを解決する2つの方法を見つけたと思います。


オプション1

このオプションは、「グループ名フィルター」を使用して NSArray を確立し、条件に一致する要素の数を持つすべてのグループを返しますが、それはゼロです (一致する要素はありません)。

"Grp" と "Elem" の 2 つのエンティティがあり、それらの間には対多の関係があります。

NSError *error = nil;

// Properties to be fetched
NSPropertyDescription *namePropDesc = [[[[self.moModel entitiesByName] objectForKey:@"Grp"] propertiesByName] objectForKey:@"name"];

// Variable group filter
NSArray *grpFilter = [NSArray arrayWithObjects:@"group_A", @"group_B", nil];

// Expression for counting elements
NSExpressionDescription *countExprDesc = [[NSExpressionDescription alloc] init];
[countExprDesc setExpression:[NSExpression expressionWithFormat:@"SUBQUERY(elems,$elem, SUBQUERY($elem.grps, $grp, $grp.name in %@).@count==%d).@count", grpFilter, grpFilter.count]];
[countExprDesc setExpressionResultType:NSInteger32AttributeType];
[countExprDesc setName:@"elementCount"];

// Create data fetching and set its properties
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Grp"];
[request setResultType:NSDictionaryResultType];
[request setPropertiesToFetch:[NSArray arrayWithObjects:namePropDesc,countExprDesc, nil]];

NSArray *results = [self.moContext executeFetchRequest:request error:&error];
NSLog(@"results = %@"results);


オプション 2

このオプションは、「グループ名フィルター」を使用して NSArray を確立し、要素を持たないグループなしの条件に一致する要素の数を持つすべてのグループを返します。

この場合、Grp、Elem、RGE の 3 つのエンティティを作成しました。RGE を他の 2 つの対多関係を維持する中間エンティティとして持つ。このオプションを使用すると、必要に応じて、グループ要素の関連付けに追加情報 (作成日など) を追加できます。Grp と Elem は相互に関係がありません。

: 実際、@count 関数を適用するには、RGE エンティティに「通常の」フィールド (名前) を作成する必要がありました。「対多関係フィールド」を使用すると、正しくカウントされません。

NSError *error = nil;


// Variable group filter
NSArray *grpFilter = [NSArray arrayWithObjects:@"group_A", @"group_B", nil];

// Create variable predicate string from "group's names filter"
NSMutableString *predicateStr = [[NSMutableString alloc] init];
for(int n=0;n<grpFilter.count;n++) {
    if(n>0) {
        [predicateStr appendString:@" AND "];
    }
    [predicateStr appendString:@"(ANY elem.rges.grp.name=%@)"];
}

// Filter to be applied
NSPredicate *filterQuery = [NSPredicate predicateWithFormat:predicateStr argumentArray:grpFilter];

// Expression for counting elements
NSExpressionDescription *countExprDesc = [[NSExpressionDescription alloc] init];
[countExprDesc setExpression:[NSExpression expressionWithFormat:@"name.@count"]];
[countExprDesc setExpressionResultType:NSInteger64AttributeType];
[countExprDesc setName:@"count"];

// Expression for grouping JUST by the group's name
NSExpressionDescription *grpNameExprDesc = [[NSExpressionDescription alloc] init];
[grpNameExprDesc setExpression:[NSExpression expressionWithFormat:@"grp.name"]];
[grpNameExprDesc setExpressionResultType:NSStringAttributeType];
[grpNameExprDesc setName:@"grpName"];

// THIS COULD JUST BE an NSPropertyDescription if you want the WHOLE "grp":
NSPropertyDescription *grpPropDesc = [[[[self.moModel entitiesByName] objectForKey:@"RGE"] propertiesByName] objectForKey:@"grp"];

// Create data fetching and set its properties
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"RGE"];
[request setResultType:NSDictionaryResultType];
[request setPropertiesToGroupBy:[NSArray arrayWithObjects: grpNameExprDesc, nil]];
[request setPropertiesToFetch:[NSArray arrayWithObjects:grpNameExprDesc, countExprDesc, nil]];
[request setPredicate:filterQuery];


NSArray *results = [self.moContext executeFetchRequest:request error:&error];
NSLog(@"results = %@",results);
4

2 に答える 2

0

すべてのグループを取得し、表示のために次のことを行いました。

Group *gr = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSSet *filtered = [NSSet set];
if ([gr.name isEqualToString:@"GroupA"]) {
   filtered = [gr.elements filteredSetUsingPredicate:
      [NSPredicate predicateWithFormat:@"any groups.name == %@", @"GroupB"]];
}
else if ([gr.name isEqualToString:@"GroupB"]) {
   filtered = [gr.elements filteredSetUsingPredicate:
      [NSPredicate predicateWithFormat:@"any groups.name == %@", @"GroupA"]];
}
else {
   filtered = [gr.elements filteredSetUsingPredicate:
      [NSPredicate predicateWithFormat:
        @"any groups.name == %@ && any groups.name == %@", 
        @"GroupA", @"GroupB"]];
}
cell.textLabel.text = 
   [NSString stringWithFormat:@"%@ has %d elements.", 
      gr.name, filtered.count] ;

これにより、例のように正しいカウントが得られます。ただし、除外されたグループがある場合でも、0 要素でリストされます。

于 2012-08-01T21:39:22.163 に答える