具有日期范围的 CoreData 复合提取的意外结果

Posted

技术标签:

【中文标题】具有日期范围的 CoreData 复合提取的意外结果【英文标题】:Unexpected result from CoreData compound fetch with date range 【发布时间】:2020-08-05 17:18:12 【问题描述】:

我有一个简单的数据模型,其中访问者(fName 和 lName)和访问(日期、评论)处于 1 米关系中。我正在尝试获取特定日期的所有访问者。为了实现这一点,我需要创建一个谓词来查找从当天开始到结束之间访问过的所有实体。我试过了:

...
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "visitor")
let filter = "ANY visits.date >= %@ AND ANY visits.date < %@"  // visits is the visitors relation to visits
let startTime = calendar.startOfDay(for: thisDay) as NSDate
let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: thisDay)! as NSDate
fetchRequest.predicate = NSPredicate(format: filter, startTime, endTime)

结果是访问日期在这一天及之后的所有访问者。因此复合谓词的第二部分无效! 我也尝试将这两个条件与 NSCompoundPredicate 结合起来,但结果是一样的。我已经尝试过具有相同复合谓词的日期类型以外的其他类型,并且这些都运行良好。因此,尽管在 Internet 上进行了大量搜索,但我不知道如何使用谓词解决这个简单的查询。

欢迎提出任何建议!

【问题讨论】:

ANY visits.date &gt;= %@ AND ANY visits.date &lt; %@ =>ANY (visits.date &gt;= %@ AND visits.date &lt; %@) ? 导致解析器错误:无法解析格式字符串“ANY (visits.date >= %@ AND visits.date 【参考方案1】:

您的谓词获取与visits.date &gt;= startDate 的(至少一次)访问和visits.date &lt; endDate 的(至少一次)访问相关的所有访问者。问题是这两个相关对象不必相同,谓词才能返回true

你需要的是一个“子查询”:来自(相关的)NSExpression documentation:

此方法创建一个子表达式,对其求值返回一个 对象集合的子集。它允许您创建 跨关系的复杂查询,例如搜索 目标对象上的多个相关值 关系。

...

子查询表达式的字符串格式为:

SUBQUERY(collection_expression, variable_expression, predicate);

其中表达式是一个谓词表达式,其计算结果为 集合,variableExpression 是一个表达式,将用于 包含集合的每个单独元素,谓词是 用于判断元素是否属于结果的谓词 收藏。

在您的情况下,它应该是(未经测试):

NSPredicate(format: "SUBQUERY(visits, $v, $v.date >= %@ and $v.date < $@).@count > 0",
            startTime, endTime)

这会获取与至少一次访问相关且日期在指定范围内的所有访问者。

【讨论】:

以上是关于具有日期范围的 CoreData 复合提取的意外结果的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 - 查找具有重叠日期范围的记录

CoreData 获取问题:获取具有特定日期数组的实体

在雪花中创建具有动态日期范围的日历表

NSPredicate 获取具有 NSDate 日期范围内的日期属性的核心数据对象

具有 after_key 和 size 的 ElasticSearch 复合聚合

具有长长值的 CoreData 的 iOS 谓词不够精确