Swift中Realm使用子查询按值筛选子元素遇问题求助
我一眼就看出你的问题所在啦——你当前的谓词逻辑是分开判断两个独立的条件:Entry里存在一个name为Night的FieldValue,并且存在一个flightTime > 0的FieldValue。但这两个条件可以匹配不同的FieldValue对象!所以哪怕某个Entry里有一个name=Night但flightTime=0的FieldValue,只要它还有另一个flightTime>0的FieldValue,就会被你的谓词选中,这显然不是你想要的结果。
你真正需要的是:筛选那些**至少有一个FieldValue同时满足name=Night和flightTime>0**的Entry,对吧?
修正后的单条件谓词写法
针对flightTime > 0的场景,把两个条件放到同一个SUBQUERY里,确保是同一个FieldValue同时满足两个要求:
let value = "Night" let predicate = NSPredicate(format: "SUBQUERY(fieldValues, $fv, $fv.name = %@ AND $fv.flightTime > 0).@count > 0", value)
SUBQUERY的作用是遍历fieldValues列表中的每一个元素,对每个元素$fv检查括号里的所有条件,最后返回符合条件的元素集合。只要这个集合的数量大于0,就说明Entry里存在符合要求的FieldValue。
扩展到三个筛选场景的组合
如果要实现你最初的需求:筛选Entry满足以下任意一种情况(对应同一个name=Night的FieldValue):
flightTime > 0bool = truetext != ''
可以用NSCompoundPredicate把三个独立的SUBQUERY谓词用OR逻辑组合起来:
let value = "Night" let flightTimePredicate = NSPredicate(format: "SUBQUERY(fieldValues, $fv, $fv.name = %@ AND $fv.flightTime > 0).@count > 0", value) let boolPredicate = NSPredicate(format: "SUBQUERY(fieldValues, $fv, $fv.name = %@ AND $fv.bool = TRUE).@count > 0", value) let textPredicate = NSPredicate(format: "SUBQUERY(fieldValues, $fv, $fv.name = %@ AND $fv.text != '' ).@count > 0", value) let finalPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [flightTimePredicate, boolPredicate, textPredicate])
这样写出来的谓词就能精准筛选到符合你预期的Entry了——只有当Entry里存在至少一个name=Night的FieldValue,并且该FieldValue满足三个条件中的任意一个时,才会被选中。
内容的提问来源于stack exchange,提问作者Clifton Labrum

