【问题标题】:CoreData NSPredicate with relationshipCoreData NSPredicate 与关系
【发布时间】:2013-05-24 05:37:30
【问题描述】:

我有以下 CoreData 对象模型

现在我在使用以下条件创建谓词时遇到问题。

获取所有DBOpportunityWHERE

DBOpportunity.stateCode == 1

DBOpportunity.invoiceDate >= GIVEN_DATE

DBOpportunityLines.crmAccept == 1 或 DBOpportunityLines.crmAccept == 3

我已经尝试了apple 提供的大量示例和编程指南,但无法做到这一点。

【问题讨论】:

    标签: ios core-data nspredicate


    【解决方案1】:

    opportunitylines 是一种对多 关系,因此一个 DBOpportunity 对象有多个 DBOpportunityLines 对象。假设最后一个条件

    DBOpportunityLines.crmAccept == 1 或 DBOpportunityLines.crmAccept == 3

    应该持有任何个相关对象,你需要一个SUBQUERY:

    NSDate *givenDate = ...;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stateCode == 1 AND invoiceDate >= %@ "
        "AND SUBQUERY(opportunitylines, $x, $x.crmAccept == 1 OR $x.crmAccept == 3).@count > 0",
        givenDate];
    

    备注: 不幸的是,在谓词中使用 SUBQUERY 的文档很少。 NSExpression 类引用中有one example。另见Quick Explanation of SUBQUERY in NSPredicate Expression

    【讨论】:

    • @Marting thanx 很多,这是一个很好的解决方案。您能否指导我对上述子查询进行轻微修改。我只想通过一个额外的条件来保留所有条件。目前,opportunitylines.crmAccept 应该是 1 或 3,如果没有机会实体的机会线,我也想包括在内。
    • @IrfanDANISH:可能类似于"stateCode == 1 AND invoiceDate >= %@ AND (SUBQUERY(opportunitylines, $x, $x.crmAccept == 1 OR $x.crmAccept == 3).@count > 0 OR opportunitylines.@count == 0)"
    • Thanx 在命中和试用期间我做到了 :)
    【解决方案2】:

    谓词的结构是A && B && (C || D)

    设置你的谓词

    NSPredicate *aPredicate = [NSPredicate predicateWithFormat:@"stateCode == %d", value];
    NSPredicate *bPredicate = [NSPredicate predicateWithFormat:@"invoiceDate >=  %@", givenDate];
    

    cPredicate 和 dPredicate 类似。然后先将 c 和 d 用 OR 组合起来

    NSArray *cdPredicateArray = @[cPredicate, dPredicate];
    NSPredicate *cdPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:cdPredicateArray];
    

    然后全部用AND

    NSArray *allPredicateArray = @[aPredicate, bPredicate, cdPredicate];
    NSPredicate *allPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:allPredicateArray];
    

    如果我误解了您的问题并且您的结构是 A && B && C || D 那么您必须先将 A、B 和 C 组合(使用 AND),然后将结果与 D 组合(使用 OR)。

    【讨论】:

    • 请注意,实体名称不是谓词的一部分,所以第一个只是... "stateCode == %d", value]
    【解决方案3】:

    您还可以获取您的opportunityLines,然后像这样获取父实体:

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"opportunityLines" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    
    NSDate *yourDate = [NSDate date];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(crmAccept==1 OR crmaccept==3) AND opportunity.stateCode==1 AND opportunity.invoiceDate>=%@", yourDate];
    [fetchRequest setPredicate:predicate];
    
    NSError *error;
    
    //So here you have your array of opportunitylines
    NSArray *opportunityLines = [context executeFetchRequest:fetchRequest error:&error];
    
    //And this is how you get your opportunity objects
    NSArray *opportunities = [opportunityLines valueForKeyPath:@"@distinctUnionOfObjects.opportunity"];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多