Core data NSPredicate检测子查询中的非空关系

Core data NSPredicate检测子查询中的非空关系,core-data,nspredicate,Core Data,Nspredicate,给定一个核心数据实体设置,如下所示 let date1970 = Date.init(timeIntervalSince1970: 0) predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child.date >= %@).@count > 0).@count > 0)" predicateVars = [date1970! as NSDate] 实体A Bs->B(多对多) Cs->

给定一个核心数据实体设置,如下所示

let date1970 = Date.init(timeIntervalSince1970: 0)
predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child.date >= %@).@count > 0).@count > 0)"
predicateVars = [date1970! as NSDate]
  • 实体A
    • Bs->B(多对多)
    • Cs->C(多对多)
    • 儿童->儿童(多对多)
  • 实体B
    • 儿童->儿童(多对多)
  • 实体C
    • 儿童->儿童(多对多)
  • 孩子
    • 日期
我想查询实体A,其中任何子实体(在实体A、B或C中)的日期都会通过一些查询,比如大于指定日期

给定嵌套关系,需要一些嵌套的子查询,因此要使用类似这样的方法检查A中的所有Bs子项

predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child.date >= %@).@count > 0).@count > 0)"
predicateVars = [testDate! as NSDate]
let predicate = NSPredicate(format: predicateString, argumentArray: predicateVars)
predicateString += " SUBQUERY(Bs, $b, $b.children.@count > 0).@count > 0"
predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, TRUE).@count > 0).@count > 0)"
对Cs重复相同形式的查询,然后只对a的直接子项执行单个子查询

在对谓词形式进行一些微调(确保添加了所有必需的计数)之后,这一切都可以正常工作

当我现在想执行类似的搜索时,出现了一个小问题,但我不要求孩子的日期大于测试日期,而是想找到所有a.children、Bs.children、Cs.children中有孩子的a

嵌套的子查询导致了问题,起初我认为最好只执行一个级别的子查询,然后检查其中的子关系计数,比如

predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child.date >= %@).@count > 0).@count > 0)"
predicateVars = [testDate! as NSDate]
let predicate = NSPredicate(format: predicateString, argumentArray: predicateVars)
predicateString += " SUBQUERY(Bs, $b, $b.children.@count > 0).@count > 0"
predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, TRUE).@count > 0).@count > 0)"
它被接受为一个有效谓词,但当它被计算时,您遇到了一个异常

[error] error: exception handling request: <NSSQLFetchRequestContext: 0x60000018ec70> , Keypath containing KVC aggregate where there shouldn't be one; failed to handle $b.children.@count with userInfo of (null)
这感觉很浪费,但可以做我想做的事。不幸的是,它无法作为有效谓词进行解析

除此之外,我还成功地提出了应该始终正确的查询,因此将日期与1970年进行了如下比较

let date1970 = Date.init(timeIntervalSince1970: 0)
predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child.date >= %@).@count > 0).@count > 0)"
predicateVars = [date1970! as NSDate]
这很管用,但感觉做的工作比我更喜欢数一数。一个更简单的例子是,只需针对nil测试每个孩子,所以

predicateString += "(SUBQUERY(Bs, $b, SUBQUERY($b.children, $child, $child != nil).@count > 0).@count > 0)"
predicateVars = [testDate! as NSDate]
这似乎更好,但我只是想知道是否有更好的选择。我真的不明白为什么真条件本身不是一个有效的谓词。。是的,这是浪费,但在这种情况下,我们似乎必须执行一个非常浪费的子查询来获得我们想要的计数


有谁有更好的主意吗?

我唯一的建议是测试一下孩子之间的关系,不知道这是否有效nil,而不是测试每个子查询:
子查询(Bs,$b,$b.children!=nil)。@count>0
。感谢您的建议,我没有尝试过,它看起来也没有什么不合理之处。不幸的是,刚刚尝试了它,我可以确认,虽然它生成了一个有效的谓词,但当我使用谓词对我的fetchedResultsController执行蚀刻时,它会引发此异常。“CoreData:错误:异常处理请求:,对于userInfo为(null)的此处不允许的多个密钥。”。我不认为有任何方法可以绕过它,你似乎必须通过子查询来获得所有元素的计数。