CoreData: Querying One-to-Many Relationships
I have a basic data model:
and I am trying to request all films showing theater with a specific schedule.
But I cannot figure out how I can fulfill this request using NSPredicate.
I've tried this:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY (movies, $x, $x.movies.showTimes == %@ AND $x.movies.theater.nameOfTheater == %@).@count >0", showTime, theater];
but doesn't work. Does any of you know what I am doing wrong?
I will be very grateful for your help.
source to share
I am assuming from your stated purpose ("... to request all movies showing theater on a specific schedule") that the object is for your NSFetchRequest Movies
. If so, the names of the attributes and relationships you are using must refer to this object. Therefore, the name of the theater will be indicated theaters.nameOfTheater
, and the time of the show will be showTimes.showTimes
. Since Movie
there are many for a given Schedules
, your predicate needs to select a movie if ANY of them showTimes.showTimes
matches your requirement. So one way to write a predicate is:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"theaters.nameOfTheater == %@ AND (ANY showTimes.showTimes == %@)", theater, showTime];
Alternatively, ANY's clause can be rewritten as SUBQUERY:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"theaters.nameOfTheater == %@ AND SUBQUERY(showTimes, $x, $x.showTimes == %@).@count > 0", theater, showTime];
As a broader recommendation, I would make some changes to the names of your attributes and entities; this will help make things clearer:
- Entity names usually have to be singular, so
Movie
notMovies
,Theatre
notTheatres
andSchedule
notSchedules
. - Likewise, the names of relationships should reflect whether they are one or to many. So the Movie object must have a relationship
Theatre
, since it is one, and the Schedule object must have a relationshipMovies
, since it is for many.
Finally, I think you could improve your data model. Currently, there can only be one theater per film. In practice, I would assume the film will be shown in more than one theater! Personally, I would have a model like this:
So each Schedule
refers to only one Movie
and one Theater
. But everyone Theater
has a lot showings
and everyone Movie
has a lot screenings
. Using this model, a predicate matching your query would look like this:
NSPredicate *moviesPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(screenings, $x, $x.theater.nameOfTheater == %@ AND $x.showTime == %@).@count > 0", theater, showTime];
source to share