2011-08-23 73 views
0

这是核心数据专家之一,我猜。也许这超出了它应该达到的范围......无论如何:核心数据谓词和表情疯狂

在iOS上,使用sqlite持久性存储。

我有实体像这样: 甲< - >> B < < - “ç

B具有属性“V”,这是一个浮子,和另一属性“d”,这是一个日期。 B与A有单一关系,'C'与C单一关系。'

我可以计算所有B.v的平均值,其中B.a == someA,代码如下。但是,我真正想要做的是计算所有B.v的平均值,其中B.a == someA,其中B是C的最后一个B,由B.d.排序。所以平均函数对于每个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

在数据模型图中是否有拼写错误?它看起来应该是'A <-->> B <<--> C'。 – TechZen

+0

是的,正确的,谢谢! – Colin

回答

0

当您使用setPropertiesToFetch:时,您告诉抓取忽略所有其他属性。这意味着你的谓词@"a == %@"被键入a属性,将被忽略。

在这种情况下,您可能想要做的事情是将@"a == %@"谓词转换为NSSubqueryExpressionType相等表达式,然后将数组中的第一个表达式传递给setPropertiesToFetch:

这将指示提取首先找到匹配@"a == %@"的所有B对象,然后针对该对象集运行v表达式。

但是,当您发现自己必须创建复杂的谓词时,通常表明您的数据模型设计不佳。通常,由于您试图在谓词中创建逻辑关系而不是在数据模型中对其进行建模,因此最终会出现复杂的谓词。

此外,通常,当你手中有特定的物体时,例如, someA和/或someC那么你根本就没有做一次提取,而是你走过关系。如果只能使用someA.bObjects,为什么要获取与someA对象相关的所有B对象?

我认为你的数据模型看起来真的是这样的:

A<-->>B<<-->C 

...和你找套someA.bssomeC.bs之间B对象的交集。所以,要做的第一件事是让集合的交集:

NSMutableSet *secSet=[[NSMutableSet setWithSet:someA.bs] intersectSet:someC.bs]; 

...现在,所有你需要做的就是找到B对象与最近的日期:

BClass *someB=[secSet valueForKeyPath:@"@max.dateAttribute"]; 

...和你完成了。迭代该过程以查找多个AC对象之间的交集。

+0

你的第一点(关于被忽略的谓词) - 我不认为它是,因为上面的代码工作正常。而且我认为我可能不得不在“代码中”而不是“在数据库中”进行这种计算。我的直觉是尝试'写入sql'(通过正确的核心数据操作)来进行计算,而不是在代码中,因为在代码中执行它会调出每个作为关系目标的对象,并且可能会有很多。也许这只是错误的思考方式。最后,关于“@ max.attribute” - 谢谢,我不知道这是可能的! – Colin