我一直在尝试使用Core Data解决以下问题而没有任何运气。
我的模型有两个实体:Group和Element。两者都具有“name”属性和to-many关系,形式为:“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等中?
感谢。
我想我找到了解决这个问题的两种方法。
此选项使用“组名称过滤器”建立一个NSArray,并返回所有具有与条件匹配的元素数量的组,即使它为零(没有元素匹配)
有两个实体,“Grp”和“Elem”,它们之间有很多关系。
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);
此选项使用“组名称过滤器”建立NSArray,并返回所有具有与条件匹配的元素数的组,而不包含没有任何元素的组。
在这种情况下,我创建了三个实体,Grp,Elem和RGE。将RGE作为一个中间实体,保持与另外两个的多对多关系。如果需要,此选项允许在组元素关联(创建日期等)中添加一些额外信息。 Grp和Elem之间没有关系。
注意:事实上,我需要在RGE实体中创建一个“常规”字段(名称)来应用@count函数。如果使用“to-many relationship字段”,则无法正确计数。
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);
答案 0 :(得分:0)
我有类似的问题,我使用&#34;选项2&#34;解决了它。方法:Grouping three entities with many-to-many relationships
的问候。 佩德罗文图拉。