CoreData:查询一对多对多的关系

Posted

技术标签:

【中文标题】CoreData:查询一对多对多的关系【英文标题】:CoreData: Query to one-to-many-to-many relationship 【发布时间】:2015-05-12 17:24:45 【问题描述】:

我有一个这样的核心数据模型:

我正在尝试查询所有放映具有特定时间表的剧院的电影。

但我不知道如何使用 NSPredicate 进行此查询。

我试过了:

NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY (movies, $x, $x.movies.showTimes == %@ AND  $x.movies.theater.nameOfTheater == %@).@count >0", showTime, theater];

但是没有用。你们有谁知道我做错了什么?

非常感谢您的帮助

【问题讨论】:

【参考方案1】:

我从您声明的目标(“...查询所有放映具有特定时间表的剧院的电影”)假设您的 NSFetchRequest 的实体是 Movies。如果是这样,您使用的属性和关系名称都应该与该实体相关。因此,剧院名称将由theaters.nameOfTheater 给出,放映时间将为showTimes.showTimes。因为给定的Movie 有很多Schedules,所以如果showTimes.showTimes 中的任何一个符合您的要求,您的谓词需要选择一部电影。所以写谓词的一种方法是:

NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"theaters.nameOfTheater == %@ AND (ANY showTimes.showTimes == %@)", theater, showTime];

或者,可以将 ANY 子句重写为 SUBQUERY:

NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"theaters.nameOfTheater == %@ AND SUBQUERY(showTimes, $x, $x.showTimes == %@).@count > 0", theater, showTime];

作为更广泛的建议,我会对您的属性和实体的名称进行一些更改;这将有助于使事情更清楚:

    实体名称通常应该是单数,所以Movie 不是MoviesTheatre 不是TheatresSchedule 不是Schedules。 同样,关系的名称应该反映它们是对一还是对多。所以 Movie 实体应该有一个关系 theatre 因为它是一对一的,而 Schedule 实体应该有一个关系 movies 因为它是对多的。

最后,我认为您可以改进您的数据模型。目前,每部电影只能有一个剧院。在实践中,我会想象一部电影将在不止一个影院放映!就个人而言,我会有这样的模型:

所以每个Schedule 只与一个Movie 和一个Theater 相关。但是每个Theater 有很多showings,每个Movie 有很多screenings。使用此模型,满足您查询的谓词将是:

NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(screenings, $x, $x.theater.nameOfTheater == %@ AND $x.showTime == %@).@count > 0", theater, showTime];

【讨论】:

以上是关于CoreData:查询一对多对多的关系的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:NSPredicate 一对多对多关系

Swift、CoreData 和多对多关系:如何访问子项的顺序?

CoreData:使用 NSPredicate 过滤一对多对多关系(此处不允许错误对多键)

如何判断一对一对多和多对多的关系

hibernate 关联关系(多对多对多一对一)的配置

CoreData 性能:基于多对多关系