我猜这是核心数据专家的一个。也许这只是超出了它应该的范围...无论如何:
在iOS上,使用sqlite持久性存储。
我有这样的实体: A< - >> B<< - &以及c
B有一个属性'v',它是一个浮点数,另一个属性'd'是一个日期。 B具有与A单一的关系'a'和与C单一的'c'。
我可以计算所有B.v的平均值,其中B.a == someA,代码如下。但是,我真正想要做的是计算所有B.v的平均值,其中B.a == someA,其中B是C的最后B,由B.d.排序。因此,对于每个C(最高日期的C),平均函数将“拾取”仅一个B。有什么想法吗?
// create the fetch request
NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"B" inManagedObjectContext:managedObjectContext]];
// create the expression
NSExpression * keyPathExpression = [NSExpression expressionForKeyPath:@"v"];
NSString * aggregationFunction = @"average:";
NSExpression * aggregationExpression = [NSExpression expressionForFunction:aggregationFunction arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription * expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"aggregateValue"];
[expressionDescription setExpression:aggregationExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"a == %@", someA];
[request setPredicate:predicate];
[request setResultType:NSDictionaryResultType];
// Execute the fetch.
NSError * error = nil;
NSArray * objects = [managedObjectContext executeFetchRequest:request error:&error];
答案 0 :(得分:0)
当您使用setPropertiesToFetch:
时,您告诉提取忽略所有其他属性。这意味着您的@"a == %@"
属性的a
谓词将被忽略。
在这种情况下,您可能想要做的是将@"a == %@"
谓词转换为NSSubqueryExpressionType相等表达式,然后将该数组中的第一个表达式传递给setPropertiesToFetch:
。
这将指示fetch首先查找匹配B
的所有@"a == %@"
个对象,然后针对该组对象运行v
表达式。
但是,当您发现自己必须创建复杂的谓词时,这通常表明您的数据模型设计不当。通常,您最终会得到复杂的谓词,因为您试图在谓词中创建逻辑关系,而不是在数据模型中对它们进行建模。
此外,通常情况下,如果手中有特定物体,例如someA
和/或someC
然后你根本不进行取指,而是走你的关系。当您可以使用B
时,为什么要获取与someA
对象相关的所有someA.bObjects
个对象?
我认为您的数据模型看起来真的像这样:
A<-->>B<<-->C
...并且您正在B
和someA.bs
之间寻找someC.bs
个对象的交集。所以,首先要做的是获得集合的交集:
NSMutableSet *secSet=[[NSMutableSet setWithSet:someA.bs] intersectSet:someC.bs];
...现在你所要做的就是找到最近日期的B
对象:
BClass *someB=[secSet valueForKeyPath:@"@max.dateAttribute"];
......你已经完成了。迭代该过程以查找多个A
和C
对象之间的交叉点。